Boost ASP.NET performance with deferred content loading
AJAX, ASP.NET, JavaScript, Performance, UI By Dave Ward. Updated October 15, 2008
When rolled into the page life cycle of an ASP.NET WebForm, that red bar is one of your application’s greatest enemies. No matter how well you optimize the rest of the page, even one slow task can become the sole factor determining a user’s perception of the entire page’s performance.
In this post, I’m going to show you one way to circumvent that problem. By placing ancillary content in user controls and delaying their load until the core page content has been displayed, you can drastically improve perceived performance.
When broken down into digestible chunks, the technique is easy to implement and lends your application a level of polish that your users are sure to appreciate. The four steps required to accomplish this will be: building the user control, statelessly rendering the control as HTML, providing progress indication, and using ASP.NET AJAX to request and inject that HTML.
Building the user control
First, we need some slow-loading, auxiliary content to encapsulate in a user control. For this example, that’s going to be a minimal RSS feed reader widget that displays the most recent posts from this site.
The key activity here is retrieving my RSS feed and querying it for some basic information. To expedite this, I’m going to use one of ASP.NET 3.5′s great new features: LINQ to XML. LINQ really makes short work of this normally tedious task. It still blows me away every time I use it.
protected void Page_Load(object sender, EventArgs e) { XDocument feedXML = XDocument.Load("http://feeds.encosia.com/Encosia"); var feeds = from feed in feedXML.Descendants("item") select new { Title = feed.Element("title").Value, Link = feed.Element("link").Value, Description = feed.Element("description").Value }; PostList.DataSource = feeds; PostList.DataBind(); }
To display this, I’m going to use another of ASP.NET 3.5′s new features, the ListView control:
<asp:ListView runat="server" ID="PostList">
<LayoutTemplate>
<ul>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li><a href='<%# Eval("Link") %>'><%# Eval("Title") %></a><br />
<%# Eval("Description") %>
</li>
</ItemTemplate>
</asp:ListView>
With a little bit of CSS (included in the source download later), this results in something resembling the screenshot to the right.
The ListView comes in especially handy for our purposes here, because it gives you such effortless control over the rendered HTML. When injecting generated HTML into a page, you really appreciate knowing exactly what markup to expect.
Rendering the user control as HTML
The next step is to create a web service that statelessly renders our user control as an HTML string. By statelessly, I mean that we need to render this user control outside the context of an active ASP.NET Page instance, where user controls are normally intended to be used.
To solve that problem, you can create a temporary instance of the ASP.NET Page class, dynamically add the user control to it, and then execute it within the web service’s context. Doing this turns out to be easier than it is to accurately describe:
[WebMethod] public string GetRSSReader() { // Create a new Page and add the control to it. Page page = new Page(); UserControl ctl = (UserControl)page.LoadControl("~/RSSReaderControl.ascx"); page.Controls.Add(ctl); // Render the page and capture the resulting HTML. StringWriter writer = new StringWriter(); HttpContext.Current.Server.Execute(page, writer, false); // Return that HTML, as a string. return writer.ToString(); }
You might worry about creating an entire Page instance for what is supposed to be a performance enhancing technique. At first, I shared the same concern.
However, since our Page instance is created outside of the normal ASP.NET HTTP pipeline and only contains one control, the overhead is negligible. The Page itself is fairly performant compared to all of the other work involved in a typical HTTP round-trip.
Setting up the demonstration page
To demonstrate, we’ll need a page with some fast-loading content to provide contrast. Inside that, we can embed an empty DIV which will be used to accurately inject the user control’s rendered HTML.
<asp:ScriptManager runat="server"> <Services> <asp:ServiceReference Path="~/RSSReader.asmx" /> </Services> <Scripts> <asp:ScriptReference Path="~/Default.js" /> </Scripts> </asp:ScriptManager> <div id="Container"> <div id="RSSBlock" class="loading"></div> <div id="Content"> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing...</p> </div> </div>
As you can see, the RSSBlock DIV is initially assigned a CSS class of “loading”. This is the CSS for the loading class:
.loading { background: url('progress-indicator.gif') no-repeat center; }
What this does is give us a bit of rudimentary progress indication. Until we update it later, it will display an empty placeholder with an indicator.
You and I know that it’s a bit of a scam, but your users will never realize the progress indicator isn’t real. I won’t tell if you won’t!
Calling the web service from JavaScript
Now that we’ve got a place to inject it, the final step is to retrieve the HTML rendering of our user control and insert it into the page. ASP.NET AJAX takes all of the hard work out of this step:
Sys.Application.add_init(AppInit); function AppInit() { RSSReader.GetRSSReader(OnSuccess, OnFailure); } function OnSuccess(result) { // Remove the .loading CSS from the div, to remove the // progress indicator background. Sys.UI.DomElement.removeCssClass($get('RSSBlock'), 'loading'); // Fill the div with the HTML generated from the user control. $get('RSSBlock').innerHTML = result; } function OnFailure() { // Do something if our callback fails. Retry it, perhaps. }
Since it’s only a CSS class, disabling the progress indication is as simple as using removeCssClass to remove it from the DIV. For more on removeCssClass, check out my recent article about ASP.NET AJAX’s client side UI methods.
With the animated background removed, we are now free to insert the rendered HTML into the DIV’s innerHTML. The end result is exactly the same as if we had placed the user control inside that DIV, without unnecessarily delaying the entire page load.
Conclusion
I think you’ll find that this technique is very powerful. It allows you to leverage your existing knowledge of ASP.NET and its server controls as a robust templating solution for lightweight AJAX. At the same time, it exudes the kind of professional usability that typically requires more tedious and less maintainable client side coding.
Note that there is not an UpdatePanel anywhere on this page. Using this technique does not require relying on partial postbacks. Not only does that improve performance, but also allows UpdatePanels elsewhere on the page to operate normally, while the deferred content loads.
Check out the full demonstration by downloading the source and running it yourself. You really have to see it in action to truly appreciate it. The download also includes at least one improvement that I didn’t have room to write about in this post. Give it a try and let me know what you think.
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.
11 Mentions Elsewhere
- rascunho » Blog Archive » links for 2008-02-05
- » Daily Bits - February 6, 2008 Alvin Ashcraft’s Daily Geek Bits: Daily links, development, gadgets and raising rugrats.
- links for 2008-02-07 « ThisIsSteve
- SitePoint Blogs » .NET on the ‘Net Feb 1-7: DataContext Dilemmas & Versioning Databases
- Using jQuery to Consume ASP.NET JSON Web ServicesEncosia @ ZDima.net
- Eye On .NET - Hisham Elbreky
- links for 2008-05-13 at James A. Arconati
- AJAX links « bnotezz
- TG Developer » .NET on the ‘Net Feb 1-7: DataContext Dilemmas & Versioning Databases
- Feb 6th Links: ASP.NET, ASP.NET AJAX, Visual Studio, .NET, WPF | OOP – Object Oriented Programing
- Enable delayed content loading for Cuyahoga Module | 老屋前的苦楝树



Nice! I’ve been looking for something like this that doesn’t use UpdatePanels. Thanks!
This is very helpful. However I found that it doesnt work when my ascx file has an infragistics chart, panels and other controls.
Thanks for this — it’s a good technique. What is the request performance monitoring tool you are showing in the first screenshot?
It’s from FireBug’s “net” tab.
Now that is a nice little trick that I might just have to steal… I mean borrow. :-)
Thanks a lot for sharing this nice approach.
This isn’t really ASP.NET performance related. It just makes the pages load “asynchronously”. A poorly written deferred-loading method, can still cause the ASP.NET server to hang.
Right, but if you isolate it, it will no longer be able to cause your entire page to hang along with it.
At a technical level you haven’t improved performance, but none of your users actually realize or care about that technical differentiation. Perception is reality to them.
Yep, you are talking about two distinct issues, speed and responsiveness. This neat little trick will not improve the speed, but it will improve the responsiveness of the site. Therefore the users perceives a faster site, and that is what is important.
Great stuff! I had this same problem when loading slow banner ads, and ended up putting them in an iframe.
Good trick to speed up the initial page load, but you must remember that this keeps the “dynamic” content from being seen by the search engines. This is a good thing to do in an application, but not in a web site for the sake of SEO.
You’re right. That’s definitely a good point to keep in mind.
What of form post backs? I suppose this only works if the usercontrol does not have asp.net form controls that handle user interaction with server side events?
You’re correct.
On the surface, this is primarily aimed at read-only content. Definitely no postbacks. However, you could provide some interactivity without too much trouble.
Consider the case of an editable GridView. You could execute a web service to update its data from the client, and then call the user control rendering web service to display the updated grid.
In my experience, this approach is tremendously faster than using an UpdatePanel to switch to edit mode and then update and rebind.
While I think this was a good demonstration, I don’t think I would use it on a busy site. You would basically be speeding up the page for the first visitor, but slowing it down for each additional.
What I would do, is render the feed inline, but cache it in memory. You shouldn’t be hitting an RSS feed continually anyway. If it’s cached in memory, it’s going to be easier on your server just putting it as part of the page, instead of having to handle another request. You would also need to set a low timeout for the feed request, so that you don’t wait too long for it. Even better, if the feed isn’t available in the first 2 seconds of a request, have the page use your technique.
But, of course, in most real world situations, either solution will be perfectly fine.
You would definitely still want to make use of the cache in the web service. This and caching don’t need to be mutually exclusive.
For whatever reason, I noticed that subsequent requests using the demo code ended up being cached somewhere automatically. I actually had to add an artificial delay in order to test the UI code effectively.
I use LoadControl, then uc.InitializeAsUserControl(this); then uc.RenderControl(htw); where htw=new HtmlTextWriter(new StringWriter());
The result is in htw.InnerWriter.ToString();
By using “this” inside the page code you don’t have to instantiate another page. I don’t know which of the two ways is better though.
The difference here is that the code is executing inside of a web service, so “this” isn’t a Page instance in that scope.
Nice – I have a similar technique that I’ve presented on that I hope to write up for ASPAlliance.com soon. Some of the code is here, which may be useful to those of you going down this path. http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx
Great post (and good comment point about the SEO factor). My only thought was also regarding Scott Guthrie’s post at http://weblogs.asp.net/scottgu/archive/2006/10/22/Tip_2F00_Trick_3A00_-Cool-UI-Templating-Technique-to-use-with-ASP.NET-AJAX-for-non_2D00_UpdatePanel-scenarios.aspx which is improved upon by Steven Smith as mentioned above.
Those are good methods for statelessly rendering more complex controls in general, but I would be hesitant to pass data in through the presentation layer in this scenario.
What sort of situation would you see using those more complex methods in?
Great post! Thanks for the info – you combined the power of declaratively stating your UI code using a user control, with the flexibility and cacheability of web service, and made it look snazzy with a slick loading UI component.
Hi all,
there’s clearly a collection of asp experts following this thread. Do any of you have a pre-Ajax way of supporting this incremental loading? I’m trying to solve the problem for an ASP.Net 2.0 application. I’ve a strong suspicion that I may be able to leave some data-bound controls as un-bound, only binding them to their dataset after others have rendered to html. I believe this would meet the aspiration of this article without ajax.
I look forward to your feedback.
cheers,
Ian
You can do this in ASP.NET 2.0. The only thing here that’s 3.5 dependent is XLinq and the ListView.
You could use ADO/XPath and a Repeater in 2.0. If you can’t install ASP.NET AJAX, or don’t want to use it, you could use jQuery or Prototype to make the web service call.
This can be done with far less overhead if you utilize a HTTPHandler instead of a webservice/invoking the page class.
You can also do this without using the ASP.NET AJAX framework.
If you have example code that you feel is better, by all means, post it.
I’d be especially interested to see a method for rendering user controls to HTML in a web service (or HTTP handler), without using a page instance.
Hi Dave,
In this instance, you would not use a user control, instead you would implement a HTTP Handler that performs your LINQ to XML query, and then formats the HTML return based upon that. Considering the simplicity of what you are returning, a simple HtmlTextWriter and a foreach loop is all that is needed.
This would have far less overhead, and about the same amount of code (since your removing the ascx markup from the equation).
I don’t think I would want to prematurely optimize it, at the expense of maintainability. A year from now, I would much rather edit a user control template than HTTP handler code.
I have a feeling it wouldn’t matter much for this anyway, since the point is to defer slow content. Saving a few milliseconds while displaying a query that takes several seconds to run isn’t going to be very significant.
Though, it would be interesting to see a quantitative performance comparison between an HTTP handler rendering the control and a web service doing it.
Are you plan to write same .pdf that contains all your tips and tricks for asp.net performance?
Hi, Ivan. I don’t have any plans to do that at this time. I may in the future though (as quite a few people have asked for that).
I noticed that you use a javacript library
“jquery-1.2.2.min.js” can you explain what it is being used for?
Thanks in advanced.
That’s jQuery. It’s used for the fade-in effect you see in the downloaded source version.
I’ve tried this approach before. But it doesn’t work if you put a asp.net button or text box or any other form elements in your control. You’ll get error message saying that form elements must be inside the form tag.
Slava: I was getting the same problem but I managed to solve it by wrapping the contents of my usercontrol in form tags with runat=”server”. This allows you to use server controls in there as well.
What modification is needed if anybody want top 5 article from a rss feed.
You could add .take(5) to the LINQ expression to do that.
This approach works well on localhost. After loading the example to a remote site Firefox and Opera work as expected. However IE7 keeps failing with RSSReader undefined. Any suggestions?
If you’re running Fiddler in IE7, try disabling it.
I had the same issue as Tobin above with the WebService not being recognised by Javascript. Keeps failing with RSSReader undefined. Any suggestions?
That could be a number of things. The first thing i would do is “view source” on the page and make sure that the JavaScript proxy is being injected.
Session state set to cookie autodetect doesn’t like it. Must be something like this http://forums.asp.net/t/1181395.aspx. Works better with the autodetect off. Thanks.
Interesting. Thanks for the followup comment.
A live demo would be nice
An idea I haven’t tried out yet, but maybe it would be a good idea to use a static instance variable for the Page object in the Web Service Class. My hope is that IIS server will put the thread to sleep for a while after a request and when another webservice request is made all static objects have persisted so there’s no need to construct the page object again, you can put a check to see if the static page is null then create a new instance. One important note though you have to remove the user control after it’s been built into the writer since the user control object will remain in the static page object.
I think you’d run into concurrency issues. What happens when two requests need to be rendered at the same time?
Hi
Inspired by the idea in the article, i did something like this
Page page = new Page();
UserControl ctl = (UserControl)page.LoadControl(“~/UserControls/SearchCriteria.ascx”);
page.Controls.Add(ctl);
StringWriter writer = new StringWriter();
HttpContext.Current.Server.Execute(page, writer, false);
return writer.ToString();
But, i am having problem with HttpContext.Current.Server.Execute(page, writer, false); . It give me an error “Error executing child request for handler ‘System.Web.UI.Page’.
” while every code in the user control is working fine.
Please help
thanx
Hi,
In my application, i try to load ascx file using
HttpContext.Current.Server.Execute
I use Icallbackeventhandler to load page asynchronously
but i get error…..
Error executing child request for handler ‘System.Web.UI.Page’.
When i make control read as normal html controls with runat=”server”…it works
for example
<asp:textbox> i change it to <input type=”text” runat=”server”> — this works,
but for controls like CalendarExtender i have the problem Error executing child request ,
is there a workaround for this? kindly let me know
My requirement is to load ascx page(having web controls), convert it to string and pass it to GetCallBackResult()
Thanks
This code and example doesn’t work.
The line above throws exeption ‘control must be placed inside a form tag with runat=server.’ which isn’t for the moment (we’re adding control into control tree of page rather than form)
I tried to create HtmlForm and add this into Page’s control tree, but still same.
Please let me know if anyone find solution.
Thanks
OK. I found solution for user controls requires server tag.
We need some post process after render control (to delete extra information of form)
here is the code
thanks.
Thanks for posting the solution that you found, Starianova.
Neo and Paul, does that method of executing an entire page work for what you need to do?
Great job dude, it’s very good thanks for you solution
I implemented something similar to this, but I am having ViewState problems. My controls is a little different though. I have a controls that collects data from the user. This control is repeated N-times according to the user’s request (a sort of repeater of controls). Then I query the control collecting all the data and sending it back to the server.
My problem is that when I try to submit the data I am getting an Invalid ViewState exception.
Any ideas?
_hector
The javascript can be simplified by actually placing the loading progress div within the div you want the content to load in. Then, simply setting the innerHTML removes the loading layer automatically.
But what if you want to re-use the loading progress div?
The two divs are necessary to get the positioning and overflow how I wanted them.
Neat solution! Question, Is there a way to make Page.RegisterStartupScript inside the user control work? My user control needs to write inline javascript. When the response returns from the web service, the script isn’t there. Thanks.
I managed to inject style and javascript by using a literal but I had to defer the script in order to make it work. Defer is only supported by IE. Style injection worked with Firefox and IE but not Chrome!
Hope that help.
Howdy Bill,
I discovered your blog a month ago and I’ve been immersed in jQuery goodness ever since. Am loving a new challenge…never really learned javascript, so this beats getting better at that!
I’ve been developing a page that makes a call to a PageMethod. It worked great until I put it into the application. The page it’s on uses URL rewriting, so the call to the PageMethod fails.
I considered moving the PageMethod to a WebService, but I’m using the technique of loading a UserControl on the fly and returning the HTML (LOVE IT!).
Problem: I need to set a property on the UserControl before calling Server.Execute(). That was no problem before…I just included a reference to the UserControl on the page and I was able to refer to it as ASP.usercontrols_mycontrol.aspx.
WebService doesn’t seem to have a similar functionality. Any ideas as to how I can access a property on the user control when it’s of type UserControl? I’d rather not use reflection (performance/something new to learn).
Any ideas??? This jQuery thing is awesome!
— Jim —
After the LoadControl method creates an instance of your user control, you’ll be able to access its properties normally. In my code example above, ctl.FooProperty = “Bar” should work.
Can someone post an example of a generic way to handle postback events with this system,
i would like to mimic the way an update panel works, but using deferred loading techniques.
meaning, loading after page load + handle postback events and render back results using the normal DOM updating methods like update panel.
Thanks.
The Javascript code is not running. I put alerts in each of the methods to make sure and get nada.
Any ideas?
Sounds like a parsing error in the JavaScript include. That’ll throw errors, and prevent any JavaScript in the include from being run.
Double check your syntax.
Thanks for your quick response? When I put the jscript directly on the page, the code runs, but it fails and the error is [object object]. I reduced the size of info being returned (it is a large dataset), and the error then becomes ‘unknown runtime error’. Your help is much appreciated!
Are there other resources that I can look at?
Does the fact that I’m using a masterpage make any difference?
With a Master Page (or any naming container), you’re going to need to adjust references to the RSSBlock ID accordingly.
See this post (especially the comments) for more on that: http://encosia.com/2007/08/08/robust-aspnet-control-referencing-in-javascript/
I get the information properly when I access the service from the .Net code… so I know the service is good.
I’ve been googling on the [object object] error I receive and can’t seem to find anything. It is also strange that when I select limited content I get “unknown runtime error”, but when I get a large return I get the [object object] error.
Here is the Jscript code:
I think your problem is probably related to your “year2007″ element not being rendered with that ClientID. Do a view source on the rendered page and double check.
Nope… it’s rendered just like that. I hate to keep bothering you… but I can’t seem to find any other info online.
If you can email me some representative code (or point me to it running online), I’ll take a look at it.
<div id=”year2007″></div>This is the element on the page and after rendering.
Great article
How do you “wiring” your updates?(like update panel triggers). I want on updating on one div, to update other two, all of them with this technique. How do you wire these divs programatically, so that every div knows if he needs to update or not.
Guys,
I have been using another way to get the rendered html of a control.
It is a datagrid that i create dynamically…
I bind it, i create the html by rendering it…
I get the results….by calling the page method.
But i have a problem i cannot seem to have a solution for no matter how i search for…Paging does not work…I added handlers for item databound and they are working, however how can i solve paging using the json instead of the update panel…
Thanks for all the help.
Chriss.
Postbacks and the events of server controls such as the DataGrid aren’t going to work in this scenario. However, it’s not very difficult to implement true client-side paging in similar fashion. See this example: http://encosia.com/2008/08/20/easily-build-powerful-client-side-ajax-paging-using-jquery/
Thanks a lot for sharing this nice approach.The javascript can be simplified by actually placing the loading progress div within the div you want the content to load in.
Hi, thank you Dave.
I had the same trouble as Tobin and Greg: RSSReader webservice is undefined. The javascript proxy was being injected, and it was defined (in my project) as jQueryPruebas.DeferredContentLoading.RSSReader, so in Default.js I changed the line in AppInit function, from:
RSSReader.GetRSSReader(OnSuccess, OnFailure);
to:
jQueryPruebas.DeferredContentLoading.RSSReader.GetRSSReader(OnSuccess, OnFailure);
and the example worked, tested in FF3 & IE8
I forgot to mention my project name is jQueryPruebas and this example is in a folder named DeferredContentLoading. The webservice namespace is jQueryPruebas.DeferredContentLoading
Cannot seem to get this to work with a gridview. I see the gridview get populated when I step through the debugger, but something is not updating the page. I’ve even simplified my test example, no luck. I do get your example working without problems.
Are you rendering the GridView within a user control, as shown in the example?
If you step through the service method in the debugger, does writer.ToString() contain the correct HTML?
Hi Dave,
Great article, just for interest, what tool did you use to get those load timings for your 10 requests graphic at the top?
Thanks
Matt
That’s a screenshot of Firebug’s “net” tab.
I’m using webservices in a similar manner to inject html on demand…however I’m finding that the output is very escaped, while I don’t need it to be. (Thus making the output much larger than I would like!)
Example:
{“d”:”\u003cp xmlns:user=\”test\”\u003e\u003cb\u003eYou must first select events for your meet, before you can enter a time schedule.\u003c/b\u003e\u003c/p\u003e”} instead of simply:
{“d”:’You must first select events for your meet, before you can enter a time schedule.‘}
Is there a way to prevent the webservice from escaping the string?
As far as I know, you can’t avoid that with ScriptServices and page methods. Their serializer (JavaScriptSerializer) treats all strings as utf-8 strings, which is the escaping you’re seeing.
why not do it this way: leave your RSS control empty with a “loading…” placeholder, and after a page load, make an AJAX call to refresh this particular control? this approach involves much less overhead on the server and improves rendering performance as well. thus you can even cache the entire dynamic page and still have it up to date.
That’s exactly what this example is doing.
I found this article is useful.
But, consider the case…my user control has some input controls like textboxes. I needs to allow the user to enter some values into it and I should able to submit the page back to server, and finally I need to save it?
While submitting the page I am getting below error…
“The state information is invalid for this page and might be corrupted.”
1. Is there any work arround for it?
2. How Can I access input controls at server side?
Regards,
Pradeep.
This won’t work well if you need the deferred content to raise postbacks. As mentioned in the article, the idea is to defer loading of ancillary content, not core features like WebForms forms.
I am trying to make this work and it seems I am losing events.
I am iterating through a list of IDs and based on each of these IDs I am loading a UserControl. Everything loads fine except that only the first of these controls is retaining events. I can’t event fire up a simple alert message from these controls.
Below is my code. I’d appreciate the help here:
public string GetBenefitControls(string benefitIds, string contactId)
{
// build list of benefit IDs from input
List benefitIdList = new List();
foreach (string item in benefitIds.Split(new string[] {“|”}, StringSplitOptions.RemoveEmptyEntries))
{
int benefitId;
if (int.TryParse(item, out benefitId))
benefitIdList.Add(benefitId);
}
// build list of benefit objects from each id
List benefitList = new List();
foreach (int benefitId in benefitIdList)
{
benefitList.Add(new Benefit(benefitId));
}
// for each control, instantiate a BenefitAtIntake control and
// load this with a Benefit object
StringBuilder benefitsAtintake = new StringBuilder();
foreach (Benefit benefit in benefitList)
{
// create the page for the call
Page page = new Page();
page.EnableViewState = false;
HtmlForm form = new HtmlForm();
form.ID = “__t”;
page.Controls.Add(form);
// create the ClientIntakeBenefitDictionary dictionary for the benefit and add it to the BenefitAtIntake control
ClientIntakeBenefitDictionary dictionary = new ClientIntakeBenefitDictionary(benefit, new Guid());
Control control = page.LoadControl(“~/UserControls/BenefitAtIntake.ascx”);
((BenefitAtIntake)control).Benefit = benefit;
((BenefitAtIntake)control).IntakeBenefitCollection = dictionary[benefit];
// create the HtmlForm for the page; and put the control in this new form
form.Controls.Add(control);
StringWriter writer = new StringWriter();
HttpContext.Current.Server.Execute(page, writer, false);
benefitsAtintake.AppendLine(writer.ToString());
writer.Close();
}
return benefitsAtintake.ToString();
}
_Hector
That’s the expected behavior. This is basically a read-only technique.
As David said, it is read-only technique. I found it better approach in scenario where you have dynamic loading of user controls. In my case, user control was grid that is dynamically loaded into the page on some cases. It causes me lots of problems, because if you want to catch events from that user control, you need it to initialize that control in Page_Init, which in some cases is not so simple.
I found out that it is much simpler and elegant to have asynchronous loading of that control on each action in the control, instead of loading control from code behind with LoadControl and then get big pain trying to wire up all things you need to in order to make it works .
Cheers
Marko
One question for you Dave…how are you managing styling of async loaded controls. My async loaded grids doesn’t have style applied because they are added to the empty page, it doesn’t matter that I append them to the page that have that styles loaded for me.
The empty page that you use to load the user control doesn’t affect styling. When you inject the rendered HTML into the “host” page, its styles will automatically apply to the content you’ve added. If your page’s styles aren’t applying as you intended, your CSS selectors may be unintentionally too specific and excluding the injected content. I’d take a look with Firebug.
hmm, must be problem with loading of RadGrid then…style is not applied to grid and I have some strange issues in firefox: RadGridNamespace is not defined
Anyone has similar issues?
Hi Dave, I’ve been using this solution with jQuery and it works incredibly well. I have a Repeater working as a “simple” GridView and to paginate the results my jQuery script access the WebMethod the “renders” the UserControl with the Repeater. I could simply return a json list and append this to my page instead of rendering the UC, but considering that my client uses IE6 still (blah!), I’m trying to avoid the use of heavy javascript in the client. My question is: is there any performance difference between WebMethods and WebServices? And is this still a good approach (render the UC via webservices/webmethods) or you recommend something better? Thanks very much!! And your website is one of the best .NET websites I know.
As far as I know, there’s no significant performance difference between a WebMethod defined in an external service and one defined inline as a Page Method. Really, an HttpHandler would be slightly faster than either. When you aren’t taking advantage of the ScriptService’s JSON handling, an HttpHandler probably makes more sense. In retrospect, I think I should have used one of those in this example.
There are definitely pros and cons to both approaches to rendering. In modern browsers, rendering JSON via a client-side template is definitely faster and is lighter on the wire, but I think your IE6 point is a good one in favor of server-side rendering. On a public-facing site, it usually makes sense to use this partial rendering method for SEO-critical content, so you can use the same server-side rendering logic for both async clients and JavaScript disabled spiders.
Thanks Dave for your response!! I’ll take a look at the HttpHandler option. Someone told me that it could be a better option. So, depending on the situation I stick with one of the three options. About the IE6, I’m developing a solution for my client’s intranet so I have no option. Unfortunately. But I already know they are starting to adopt iPhones and Ipads as well… so hopefully we will soon move forward and leave the crap IE 6 behind. Thanks again for your support.
I’m getting
Error executing child request for handler ‘System.Web.UI.Page’
My user control contains Ajax Accordion.
What am I doing wrong.
Thanks
Great and helpfull posting for me. A pitty, that I haven’t found it earliert. It would save me plenty of time. I find also other postings in your blog very helpfull. Thx
Dave,
First of all thanks a lot for posting this.. I have been looking for this from ages.
I have got a page with number of user controls on it and as a result it takes lot of time to load. I read your article and decided to implement you r suggestion. Fortunately, everything worked fine except one problem. One of my user controls reads data from session and that’s where I am getting following exception (previously same code was working fine).
I tried to enable sessionstage (custom mode) in config as wel as at page level but no luck.
Please let me know what could be done to make your solution work with sessions?
Exception:
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the \\ section in the application configuration.
Naimish Dave
Very nice article.
Can is it possible to use the get method of json and submit the request to aspx page instead of using httphandler.
Thanks
Shashikant
I recommend against using regular code-behind in an ASPX page because those requests will have to filter through the entire page life cycle, even though you don’t really want or need all of that overhead.
Thanks for your useful website and efforts !!!
Dave,
Thanks for the comment in the other post. I have implemented it here: http://www.limitedsecurities.com/default.aspx and it is a completely different experience. The pageload has also reduced a lot, so thanks A LOT for your suggestion!
Regards,
Miguel
Hi Dave,
Thanks a lot for this solution. It works perfectly for static read-only contents, but is there anyway to allow server controls post-back events such as asp:button or dropdownlist?
I am using your solution to load multiple user controls on a website’s dashboard and some of them includes buttons and dropdownlists to filter a gridview.
I tried many solutions using Telerik AjaxManager but non of them allowed me to load all the user controls asynchronously at the same time, the ajaxRequests are made serially one after another which is waste of time and not actually asynchronous like your solution.
I want to stick to your method and hopefully it’s possible to allow server controls events.
Thanks in advance and best regards,
Osama