Rendering an ASP.net UserControl to a String

I have been converting one of my side projects from ASP.Net WebForms to ASP.Net MVC.  In order to reuse some of my existing ASP.net UserControls from WebForms in ASP.Net MVC, I tweaked a rending method found here and here.

I improved on these methods by enabling the caller of the utility function to be the one to set properties on the UserControl in a strongly typed fashion. The is no reflection or any other special interface needed on the user control.  The key was adding a callback.

Here is what it looks like to call and render the control to a string by the caller.  In this example I am rendering my GoogleMap UserControl to a string.  The last argument I am passing is an anonymous method that is called by the utility function to initialize my control.

UIUtil.RenderUserControl<GoogleMap>("~/UserControls/GoogleMap.ascx",
    uc =>
    {
        uc.CollegeToShow = CollegeToShow;
        uc.Height = Height;
        uc.Width = Width;
        uc.Mode = Mode;
    });

The helper method is as follows:

public delegate void InitializeControlDelegate<T>(T ControlToUse);

public static string RenderUserControl<T>(string ControlPath, InitializeControlDelegate<T> InitControlCallback) where T : UserControl
{
    System.Web.UI.Page pageHolder = new Page();
    T ControlToRender = (T)pageHolder.LoadControl(ControlPath);
    pageHolder.Controls.Add(ControlToRender);
    InitControlCallback.Invoke(ControlToRender);
    StringWriter result = new StringWriter();
    System.Web.HttpContext.Current.Server.Execute(pageHolder, result, false);
    return result.ToString();
}

This method uses a similar technique as to the methods linked above, but it has a callback which calls back the anonymous method that I declared in the caller.  The callback method passes back a strongly typed UserControl as the argument that we can use to set properties on the initialized UserControl.

That is all you need to make it all work.  To make things a little nicer for myself I added “RenderToString” methods on my UserControls.  If you can’t update the UserControls themselves you can just stick code like this in a helper library.

public partial class GoogleMap : System.Web.UI.UserControl
{
    public static string RenderToString(Item ItemToShow, string Height, string Width, Constants.MapMode Mode)
    {
        return UIUtil.RenderUserControl<GoogleMap>("~/UserControls/GoogleMap.ascx",
            uc =>
            {
                uc.ItemToShow = ItemToShow;
                uc.Height = Height;
                uc.Width = Width;
                uc.Mode = Mode;
            });
    }
}

Now from within my Asp.Net MVC page (or any place else), I can render my ASP.net WebForms UserControl Google Map like so:

<%=GoogleMap.RenderToString(ItemToUse, "250px", "100%", Constants.MapMode.SingleItem)%>

Cheers,

Jon

14 Responses to “Rendering an ASP.net UserControl to a String”

  1. Programming news: Alpha Five, IronPython, Scala, F# | Programming and Development | TechRepublic.com

    [...] Jon Kragh has a useful tip that shows you how to render an ASP.NET User Control as a string. This is particularly useful for the ASP.NET MVC folks out there. [...]

  2. Thomas

    Hey Jon – thanks for this, this adds some really nice features to Scott Gu’s solution. Your solutions here makes this a really extendable control loader – nice work!

  3. Jon Kragh

    Hi Thomas!

    Thanks for the feedback, it is really cool that you got use out of it. It makes it worth writing the post!

    Jon

  4. Bharath

    Good one and it help me… thanks for your code snippet.

  5. Javier Callico

    Hi Jon

    Very elegant generic wrapper, thanks.

    I replaced the InitializeControlDelegate with Action in order to avoid declaring the delegate.


    public static string RenderUserControl(string ControlPath, Action InitControlAction) where T : UserControl
    {
    System.Web.UI.Page pageHolder = new Page();
    T ControlToRender = (T)pageHolder.LoadControl(ControlPath);
    pageHolder.Controls.Add(ControlToRender);
    InitControlAction(ControlToRender);
    StringWriter result = new StringWriter();
    System.Web.HttpContext.Current.Server.Execute(pageHolder, result, false);
    return result.ToString();
    }

  6. Javier Callico

    Please remove my previous comment since some characters were removed after submitting.

    Thanks.

  7. Jon Kragh

    Hey Javier!

    Thanks for the kind words! And I like your solution, less code!

    I’m going to keep your other comment, because I’m not sure if anything was stripped out now that I’m looking at it. Plus it gives good context to other viewers that we don’t need another delegate.

    Good Job!
    Jon

  8. Javier Callico

    You can find the modified version I’m using here:
    http://codepaste.net/71sar6

  9. Jon Kragh

    Javier, very nice!!!

  10. Asif

    Control ” of type ‘Pager’ must be placed inside a form tag with runat=server.

    What is the solution of this issue since this has been reported as a bug by microsoft. I wonder WHY your code worked for you and not worked for me.

  11. Lasi

    Excellent piece of code. Really good stuff.

  12. John

    This is great, thanks. What’s the performance hit like on it though, is it much different to the control being rendered normally?

  13. Link.fr

    RenderUserControl is very useful. Thanks for this great post!

  14. Barker

    Sorry for reviving this old post.

    The above solution worked perfectly for me, until I added a GridView component in my UserControl. When I did, I got the “…must be placed inside a form tag with runat=server.” message.
    Odd thing is I have added other server side controls in the UC without any problem.

    Is this specific to databound controls? Any hints appreciated…

    Either way, thanks for the code! =)

Leave a Reply