How to render asp.net control to HTML string by code

Sometimes you will need to programatically get the HTML markup of a server or a user control that normally will be rendered to the HTTP response by the ASP.Net framework.

This can simply be done with something like this:

/// <summary>
/// Returns the generated HTML markup for a Control object
/// </summary>
private string RenderControl(Control control)
{
      StringBuilder sb = new StringBuilder();
      StringWriter sw = new StringWriter(sb);
      HtmlTextWriter writer = new HtmlTextWriter(sw);

      control.RenderControl(writer);
      return sb.ToString();
}

This is simple but unfortunately not enough to help us unless you already in the scope/life cycle of a  System.Web.UI.Page and the control that you are dealing with is already in the control tree of that page; which is not always the case.

One of the problems we will usually face -if not inside a page scope- is if the control we are dealing with requires to be inside of a runat=”server” form. If this is the case you will be facing an exception telling you that you have to add the control inside of a from. You can fix that by creating a new Page and a new HtmlForm object and hook thinks together like that:

//initialize a new page to host the control
Page page = new Page();

//create the runat="server" from that must host asp.net controls
HtmlForm form = new HtmlForm();
form.Name = "form1";
page.Controls.Add(form);
form.Controls.Add(control);
//call RenderControl method to get the generated HTML
string html = RenderControl(control);

Then you will be facing the last exception RegisterForEventValidation can only be called during Render(); . Actually I couldn’t fix this without disabling event validation on the newly created page which in my case makes a lot of sense. You disable event validation on the page like this:

page.EnableEventValidation = false;

A complete solution

This is a complete solution that makes use of a Generic Handler that renders a .ascx user control as an HTML document:

using System;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Text;
using System.IO;
using System.Web.UI.HtmlControls;

namespace UserControlHandlerDemo.Web
{
    /// <summary>
    /// Renders a (.ascx) user control
    /// </summary>
    public class UserControlHandler : IHttpHandler, IRequiresSessionState
    {
        private const string BASE_DIRECTORY = "~/controls/";

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";

            //get name from GET or POST parameter
            string controlName = context.Server.UrlDecode(context.Request.Params["name"]);
            if (!string.IsNullOrEmpty(controlName))
            {
                try
                {
                    //define full virtual path
                    var fullPath = BASE_DIRECTORY + controlName;
                    
                    //initialize a new page to host the control
                    Page page = new Page();
                    //disable event validation (this is a workaround to handle the "RegisterForEventValidation can only be called during Render()" exception)
                    page.EnableEventValidation = false;
                    
                    //create the runat="server" from that must host asp.net controls
                    HtmlForm form = new HtmlForm();
                    form.Name = "form1";
                    page.Controls.Add(form);

                    //load the control and add it to the page's form
                    Control control = page.LoadControl(fullPath);
                    form.Controls.Add(control);

                    //call RenderControl method to get the generated HTML
                    string html = RenderControl(page);
                    
                    //output it to the response stream
                    context.Response.Write(html);
                }
                catch (Exception ex)
                {
                    //output error messege to the response stream
                    context.Response.Write("Error: " + ex.Message);
                }

                //end the response
                context.Response.End();
            }

        }


        /// <summary>
        /// Returns the generated HTML markup for a Control object
        /// </summary>
        private string RenderControl(Control control)
        {
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            HtmlTextWriter writer = new HtmlTextWriter(sw);

            control.RenderControl(writer);
            return sb.ToString();
        }




        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    
    }
}

Advertisements
This entry was posted in Software and tagged , . Bookmark the permalink.

7 Responses to How to render asp.net control to HTML string by code

  1. olga says:

    very helpful and interesting

  2. harouny says:

    Thanks Olga, glad that it helped

  3. Jisme uki says:

    I have a DataRepeater inside the usercontrol which needs to be binded prior to rendering the usercontrol. But it keeps telling me that the DataReapeater does not exists when I try binding.

  4. harouny says:

    How you are trying to bind the DataRepeater? A logic like this should be inside the user control. Can you send me a code sample of what you are trying to do?

  5. Dinesh says:

    Hi,
    My scenario is lit bit different.Are the above mentioned code work if i want to Render the complete asp.net Page into .html format and save it.
    I want to Download the Page which i am generating through asp.net but i dont play it in browser.I want that what ever the Page is make.it would download that page in .html format.Like in Wix.com

  6. Pingback: [RESOLVED]Problem with RenderControl | ASP Web Form Data Control

  7. Pingback: [RESOLVED]Problem with RenderControl | ASP.NET MVC

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s