Some times wewant to generate some dynamic HTML andreturn it through a web service or something like that. Maybe we already have a user control for this purpose which is used somewhere else in our application and we don’t want to duplicate ourcode. We want to render a user control programmatically while making sure that the ASP.NET page life cycle is still run – including running the
Page_Load() method.
The
Control class (which
UserControl extends from) has a
RenderControl() method which kinda does what we want, except it doesn’t call the page event methods like
Page_Load(). This is usually where all the control initialization logic is placed and you will probably not end up with the HTML you expected, as the control wasn’t initialized.
We could go ahead and make
Page_Load() public or make a public
Initialize() method which then calls
Page_Load() and call this before werender ourcontrol, but then wehave to remember to call that method each time we want to render the control and wemight end up with
Page_Load() being run multiple times. In general it’s just not a very elegant solution in my eyes.
However, by scouring Stack Overflow I’ve found a way to do this while ensuring that all the page events are run as they normally would be. I’ve made a simple extension method for the
UserControl class which makes it very easy to get the rendered HTML from a user control while ensuring the control goes through the usual ASP.NET page life cycle events.
using System.IO; using System.Web; using System.Web.UI; namespace YourNamespace.Extensions { public static class UserControlExtensions { public static string RenderHtml(this UserControl control) { using (var sw = new StringWriter()) { var page = new Page(); page.Controls.Add(control); HttpContext.Current.Server.Execute(page, sw, false); return sw.ToString(); } } } }
With this simple extension method for
UserControl you can get the rendered HTML like this:
var control = (MyUserControl) LoadControl("~/UserControls/MyUserControl.ascx"); var html = control.RenderHtml();
If you are not in doing this in a code behind file of a page (.aspx) or a user control (.ascx) then you won’t have access to the
LoadControl() method directly. You will have to create a new
System.Web.UI.Page object and call its
LoadControl() method.
var page = new System.Web.UI.Page(); var control = (MyUserControl) page.LoadControl("~/UserControls/MyUserControl.ascx");
To make this a little simpler and more readable, you can make a simple utility method to wrap this and add it to a static utility class in your project.
public static class UserControlUtils { public static T LoadControl<T>(string virtualPath) where T : System.Web.UI.Control { return (T) new System.Web.UI.Page().LoadControl(virtualPath); } } var control = UserControlUtils.LoadControl<MyUserControl>("~/UserControls/MyUserControl.ascx");
Conclusion
So that’s it. While it isn’t that well documented and can be quite hard to find on google, it actually is possible and quite easy to render the HTML of a user control while ensuring that the ASP.NET page life cycle is still being run.
Wrapping the logic in an extension method makes it easily accessible, results in fewer lines of code and makes your code easier to read.