RenderPartial controls rendered first when extending ViewMasterPage

Last post 04-26-2009 7:53 PM by MartinF. 4 replies.

Sort Posts:

  • RenderPartial controls rendered first when extending ViewMasterPage

    01-11-2009, 8:55 PM
    • Member
      30 point Member
    • Nik Coughlin
    • Member since 09-24-2008, 5:46 AM
    • Auckland, New Zealand
    • Posts 15

    I have a class that extends ViewMasterPage called ExtendedViewMasterPage (imaginative, I know).

    The purpose of the class is to do some filtering on the HTML before outputting it, which it does by overriding Render on the ViewMasterPage: 

    protected override void Render( HtmlTextWriter writer ) {
    using ( var memoryStream = new MemoryStream( ) ) {
    using ( var streamWriter = new StreamWriter( memoryStream ) ) {
    using ( var htmlTextWriter = new HtmlTextWriter( streamWriter ) ) {
    base.Render( htmlTextWriter );
    htmlTextWriter.Flush( );
    memoryStream.Position = 0;

    TextReader textReader = new StreamReader( memoryStream );
    String output = textReader.ReadToEnd( );
    String newOutput = RewriteOutput( output );
    writer.Write( newOutput );
    }
    }
    }
    }

    RewriteOutput just does some stuff to the page, it's irrelevant because the problem occurs with or without it.

    This works very well unless there is a RenderPartial somewhere on the page... when this is the case, the output of the RenderPartial appears first, followed by the rest of the page.  So instead of, say (simplified example):

    <html>
    <body>
    <h1>Example</h1>
    <div id="login">
    [ <a href="Login">Login</a> ]
    </div>
    <div id="content">
    <p>Lorem ipsum etc.</p>
    </div>
    </body>
    </html>

    What I actually get is this: 

    [ <a href="Login">Login</a> ]
    <html>
    <body>
    <h1>Example</h1>
    <div id="login">
    </div>
    <div id="content">
    <p>Lorem ipsum etc.</p>
    </div>
    </body>
    </html>
    I tried having a poke around with Reflector but I got a bit overwhelmed trying to trace my way around.  Any ideas?
  • Re: RenderPartial controls rendered first when extending ViewMasterPage

    01-11-2009, 10:30 PM
    • Member
      30 point Member
    • Nik Coughlin
    • Member since 09-24-2008, 5:46 AM
    • Auckland, New Zealand
    • Posts 15

    Something that would be just as useful as knowing why the above happens, or a workaround for it, would be some help in reflecting RenderPartial.

    By using Reflector I find that RenderPartial calls RenderPartialInternal under the hood.

    The line in RenderPartialInternal that does the work is:

    FindPartialView(engine, viewContext, partialViewName).Render(viewContext, this.ViewContext.HttpContext.Response.Output);

    So what I need to see is Render... however because FindPartialView returns an IView Reflector just gives me the method signature for IView:

    void Render(ViewContext viewContext, TextWriter writer);

    Not very helpful, but that's OK, because I can go into FindPartialView to find out what the actual type is that's implementing IView and look at the Render method there, right?

    ViewEngineResult result = engine.FindPartialView(viewContext, partialViewName);
    if (result.View != null)
    {
    return result.View;
    }

    So now I know to go to ViewEngineResult and see what type it's View property is so I can find the code for that Render method above...

     
      public IView View

    {
    [CompilerGenerated]
    get
    {
    return this.k__BackingField;
    }
    private [CompilerGenerated]
    set
    {
    this.k__BackingField = value;
    }
    }
     

    ...and now I'm officially out of my depth Smile  These are auto-generated properties right? Like:

    public string something { get; set; }  

    So the View property is getting set somewhere else?  Anyone familiar with the MVC source and knows what is going on here?  Or do I have to *sigh* decompile and step through?  I can see that being a bit of a headache, sometimes Reflector doesn't decompile properly and I don't know if I'm up to fixing it if that happens

  • Re: RenderPartial controls rendered first when extending ViewMasterPage

    01-11-2009, 11:18 PM
    • Member
      30 point Member
    • Nik Coughlin
    • Member since 09-24-2008, 5:46 AM
    • Auckland, New Zealand
    • Posts 15

    Right, after much head scratching I have a workaround.  I'm posting it here for the benefit of anyone else who runs into this probem, however please don't mark this as solved just yet as I'd like to get to the bottom of this properly, what I have here is just a hack Smile

    Finding this was really just a stroke of luck... I wanted to see what if anything I could find regarding that Render method I talk about in my first reply to myself above, so I did a search for mvc RenderPartial Render method.

    I ended up finding the blog of a guy who had written a RenderPartialToString method

    I changed it slightly to be an extension method, doing away with the need to pass so many args in (nb. needs MvcContrib):

        /// Extension method to render partial to string - based on http://www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc/
    public static string RenderPartialToString( this HtmlHelper htmlHelper, string userControl ) {
    ControllerContext controllerContext = htmlHelper.ViewContext.Controller.ControllerContext;
    HtmlHelper temporaryHelper = new HtmlHelper( new ViewContext( controllerContext, new WebFormView( "omg" ), null, null ), new ViewPage( ) );
    var blockRenderer = new BlockRenderer( controllerContext.HttpContext );

    string s = blockRenderer.Capture(
    ( ) => RenderPartialExtensions.RenderPartial( temporaryHelper, userControl, htmlHelper.ViewData )
    );

    return s;
    }

    Voila.  Works perfectly and no longer stuffs up my page. Anybody see anything terrible about this workaround?

    Again, still interested in sorting this out properly if anyone can help.

  • Re: RenderPartial controls rendered first when extending ViewMasterPage

    01-19-2009, 8:26 AM
    • Member
      10 point Member
    • Herne
    • Member since 05-20-2008, 3:02 PM
    • Posts 12

     Nice work... :) I don't suppose you have a unit test for this?

     Thanks

  • Re: RenderPartial controls rendered first when extending ViewMasterPage

    04-26-2009, 7:53 PM
    • Member
      81 point Member
    • MartinF
    • Member since 06-15-2005, 8:34 PM
    • Denmark
    • Posts 35

    Do like this instead, it is much more simple http://thriftybliss.spaces.live.com/blog/cns!58DA805F37F31F20!170.entry

     

Page 1 of 1 (5 items)