Home > C# > ASP.NET WebForms LazyPanel: Deferred content loading in webforms

ASP.NET WebForms LazyPanel: Deferred content loading in webforms

One of the issues we face when developing a public website in webforms is the loading of contents asynchronously for improving the page load speed the user experiences. This is really common for MVC based applications, where each content could be retrieved from a different controller using AJAX, but for webforms it is a litte bit more complicated, especially if you already have the application working with all the events and postbacks and your users feels the application running slower because you are just loading too much information in one shot.

I faced this problem recently in an e-commerce like application where in the home page the most important thing is the search panel and the rest is just… “not so necessary” information. The application should take almost nothing to show the search panel and then start showing the contents, so the users can avoid waiting and just find whatever they want. Thinking about that with my friend and co-worker Javi, we got into a solution :).

The basic idea is to have a control that instead of rendering the html, renders a nice please wait and registers an ajax call that retrieves the content. This could be done in Webforms overriding the Render( HtmlTextWriter ) method.

Next we needed to store the original rendering somewhere, we chose a cache. Let’s see some code:

protected override void OnPreRender(EventArgs e)
{
	base.OnPreRender(e);
	var script = string.Format(ControlFormat, ClientID, Page.Server.UrlEncode(cacheKey));
	Page.ClientScript.RegisterStartupScript(GetType(), cacheKey, script, true);
}

protected override void Render(HtmlTextWriter writer) 
{
    string content;
    using (var stringWriter = new StringWriter())
    {
          using (var lazyWriter = new HtmlTextWriter(stringWriter))
                 base.Render(lazyWriter);

          content = new LazyContent(stringWriter.ToString(), remove, cache);
    }
            
    Page.Cache.Insert(cacheKey, content);
    
    RenderWaitImage(writer);
}

The js script requests an url like LazyContent.axd?key=, this is managed by an HttpModule that looks like:

public class LazyHandler : IHttpHandler
{
	public void ProcessRequest(HttpContext context)
	{
		var key = context.Request.QueryString["Key"];
		var content = (string)context.Cache[key]; 
		if (content == null)
			throw new LazyContentMissingException();

		context.Response.Write(content.Value);

		context.Cache.Remove(key);
	}

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

There’s an issue with the output cache, because for the cached responses the cached content won’t exist in the cache. In the following days I will be posting about how I handled that (don’t worry, it works!).

You can see the code here. It contains more features, like a loading delay, output cache support, etc.

EDIT: Source code updated with MirrorMirror newest version in order to remove the last classic reflection call.

Advertisements
Categories: C# Tags: , , ,
  1. Javier Wamba
    June 17, 2010 at 12:24 am

    Tener en cuenta que para que funcione en IIS7 se debe declarar el handler de la siguiente manera:

    xd” validate=”false” type=”IvoWiblo.LazyPanel.LazyHandler, IvoWiblo.LazyPanel”/>

    Saludos!

  2. Simon O'Gorman
    May 25, 2017 at 3:18 am

    any chance you migrated to another repo before googlecode closed ?

    I would really like to see this code.

  1. No trackbacks yet.

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

%d bloggers like this: