A simple include for ASP.NET

(c) 2005 Bertrand Le Roy In yesterday’s post, I alluded to a simple include extension method that I like to use when I don’t care about designer support. In a comment, Andrew asked if I could share the code for it, so here it is.

I never liked the regular way of including user controls in WebForms and how they require a registration and a declaration, both of which are more verbose than they need to be. A plain #include would work but is a little outdated (and if I’m not mistaken it’s not even available by default in IIS7).

My Include method is quite similar to MVC’s RenderPartial except that it doesn’t deal with view data. It’s a plain and simple include. Just give it the relative path to a user control:

<% this.Include("Header.ascx"); %>

Here’s the code for that extension method:

using System.Web;
using System.Web.UI;

public static class IncludeHelper {
    public static void Include(this TemplateControl host,
string virtualPath) { var resolvedPath = host.ResolveUrl(virtualPath); var include = host.LoadControl(resolvedPath); using (var writer =
new HtmlTextWriter(host.Page.Response.Output)) { include.RenderControl(writer); } } }

It just resolves the path, loads the control and renders it in place.

To use that method, just drop the code as a cs file into App_code if you’re using a web site, or just add it to your project otherwise.

I played with the idea of enabling an anonymous object parameter to set properties on the user control, but I guess if you’re going to do that, the benefits of the helper get dimmer and going with the regular WebForms user control registration and tags is probably just easier (you’ll get IntelliSense on the properties for example).

Disclaimer/update: No, this does not run the control through the page lifecycle (although it could by adding it to the page’s control tree and removing it after rendering it). No, if you use master pages you probably don’t need it. No, you can’t set properties.

This is just the simplest include I could build, and it does only that: including contents. If it seems useless to you, it probably is. I published it mainly because I was asked to. :)

Update: I wrote a more complex version that can set properties on the included controls:
http://weblogs.asp.net/bleroy/archive/2009/07/10/a-less-simple-include-for-asp-net.aspx

10 Comments

  • Bypasses page lifecycle of course.. that include better not require script references, postback data, etc... basically, render-only stuff.

    Any reason for not using ResolveUrl instead of Path.Combine? If you have an include within an include and the inner one is in a different directory wouldn't it resolve incorrectly?

  • @Dave: resolveUrl resolves into a client url, not exactly the same thing although it might very well give the same results. Good point about include within includes. You might want to use app-relative paths then, I suppose.

  • I just register all of my controls in the web.config, then I never have to worry about registering them on a page-by-page basis. Of course, I still have to do that 1 registration in the web.config, but its easy to copy and paste one, especially if you organize all of your controls into one directory.

    Plus, I think you would need the declarative approach to set Properties on the control. In this case, you're including some sort of header, but if its just some sort of "static" header, why not just throw the reference in the master page?

  • @John: that's absolutely right (see my previous post about master pages).

  • Presumable, that should be:


    instead of:


    Otherwise, the control output will come before the page output.

  • @Richard: no. blocks are executed during render so the include will go in place. Plus, the method is not returning anything so the wouldn't do anything.

  • Oh and this.ResolveUrl will use the current template path as the base, so app relative paths wouldn't be necessary.

  • @Dave: you win :) I've updated the code to use ResolveUrl and it works fine. I've also changed the type of the first parameter to TemplateControl so that you can now use Include in both pages and user controls.

  • This is nice. I have a similar widget based include system built into AtomSite (free open-source) and it supports scripts and tail script. Source code is on codeplex.

  • Thx for the info:

    In Vb.Net

    Public Shared Sub Include(ByRef Pagina As TemplateControl, ByVal Archivo$)
    Pagina.LoadControl(Pagina.ResolveUrl(Archivo)).RenderControl(New HtmlTextWriter(Pagina.Page.Response.Output))
    End Sub

    Usage:

    Include(Me, /MiControl.ascx")

Comments have been disabled for this content.