Skip navigation

Dynamically Load Cached User Controls (and Live to Tell About It)

Learn to recognize — and avoid — this common caching snafu.

Hot Tip

LANGUAGE: C#

ASP.NET VERSIONS: 1.0 | 1.1

 

Dynamically Load Cached User Controls (and Live to Tell About It)

Learn to recognize - and avoid - this common caching snafu.

 

By Jeff Prosise

 

Quick: can you spot the fatal flaw in the following ASPX file and the accompanying user control (ASCX file)? It's a common problem that ASP.NET developers encounter all the time - one that causes the page to throw an exception every time it's loaded. And it's one for which the solution is far from obvious:

 

<!-- Time.aspx -->

<%@ Import Namespace="System.Drawing" %>

<%@ Register TagPrefix="user" TagName="TimeControl"

  Src="Time.ascx" %>

 

<html>

  <body>

    <h1><asp:PlaceHolder ID="Here" RunAt="server" /></h1>

  </body>

</html>

 

<script language="C#" runat="server">

void Page_Load (Object sender, EventArgs e)

{

    Control control = LoadControl ("Time.ascx");

    Here.Controls.Add (control);

     ((TimeControl) control).BackColor = Color.Yellow;

}

</script>

 

<!-- Time.ascx -->

<%@ Control ClassName="TimeControl" %>

<%@ Import Namespace="System.Drawing" %>

<%@ OutputCache Duration="5" VaryByParam="None" %>

 

<asp:Label ID="Output" RunAt="server" />

 

<script language="C#" runat="server">

public Color BackColor

{

    get { return Output.BackColor; }

    set { Output.BackColor = value; }

}

 

void Page_Load (Object sender, EventArgs e)

{

    Output.Text = DateTime.Now.ToLongTimeString ();

}

</script>

 

The problem is that the Page_Load code that loads and initializes the user control assumes the control's type is TimeControl. That's a valid assumption if the control isn't cached, but the presence of an @ OutputCache directive in the ASCX file means that LoadControl returns a reference to a System.Web.UI.PartialCachingControl object rather than a TimeControl object, producing an InvalidCastException in the preceding code.

 

Here's the proper way to dynamically load and initialize a user control, independent of whether the control is cached. Note how the cached control's BackColor property is accessed: through the TimeControl reference stored in PartialCachingControl's CachedControl property. Also note that Page_Load verifies that CachedControl isn't null before using it. That's because CachedControl holds a valid TimeControl reference when LoadControl actually loads the control, but equals null when LoadControl retrieves the control from the cache:

 

<!-- Time.aspx -->

<%@ Import Namespace="System.Drawing" %>

<%@ Register TagPrefix="user" TagName="TimeControl"

  Src="Time.ascx" %>

 

<html>

  <body>

    <h1><asp:PlaceHolder ID="Here" RunAt="server" /></h1>

  </body>

</html>

 

<script language="C#" runat="server">

void Page_Load (Object sender, EventArgs e)

{

    Control control = LoadControl ("Time.ascx");

    Here.Controls.Add (control);

 

    TimeControl time = null;

    if (control is TimeControl)

        time = (TimeControl) control;

    else if (control is PartialCachingControl &&

         ((PartialCachingControl) control).CachedControl != null)

        time = (TimeControl)

             ((PartialCachingControl) control).CachedControl;

    if (time != null)

        time.BackColor = Color.Yellow;

}

</script>

 

When loading user controls dynamically, structure your code this way and it will work with or without an @ OutputCache directive in the ASCX file. Do it the other way, however, and you're in for a nasty surprise if, after you've tested the page, someone adds a caching directive to the ASCX file.

 

Jeff Prosise is author of several books, including Programming Microsoft .NET (Microsoft Press). He also is a co-founder of Wintellect (http://www.wintellect.com), a software consulting and education firm that specializes in .NET. Contact Jeff at [email protected].

 

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish