Welcome to AspAdvice Sign in | Join | Help

CodeFileBaseClass in @Control and @Page directives (via a sample)

Alan presented a question on microsoft.public.dotnet.framework.aspnet

I have a user control which I am trying to load dynamically, but am
running into problems. I think the problem is because I have two .ascx
files that refer to the same .ascx.cs file.

A simple example is like this...

Ferret1.ascx
=========
<%@ Control Language="C#" CodeFile="Ferret.ascx.cs" Inherits="Ferret" ClassName="Ferret" %>
One - <asp:Literal ID="litFerretName" Runat="Server" />

I have another one Ferret2.ascx which is exactly the same, except for
the fact that the "One" is changed to "Two" so I can see which is which
on the page.

The code-behind file looks like this...

Ferret.ascx.cs
===========
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

public partial class Ferret : UserControl {
  public void DisplayFerret() {
    litFerretName.Text = "hello";
  }
}

Now, in the calling page, I have a Placeholder called plcFerret. The
code in the code-behind for the page looks like this...

          Ferret ctlFerret1 = (Ferret)LoadControl("Ferret1.ascx");
    ctlFerret1.DisplayFerret();
    plcVole.Controls.Add(ctlFerret1);

    Ferret ctlFerret2 = (Ferret)LoadControl("Ferret2.ascx");
    ctlFerret2.DisplayFerret();
    plcVole.Controls.Add(ctlFerret2);

The first control loads fine, but the second one gives an error of
"Unable to cast object of type 'ASP.Ferret' to type 'Ferret'" on the
line where it tries to load Ferret2.ascx.

Any ideas?

Steps to make it work

1. Create a class into App_Code

public class BaseFerret : System.Web.UI.UserControl
{
    protected Literal litFerretName;

    public void DisplayFerret()
    {

        litFerretName.Text = "hello";
    }
}

2. Modify Ferret.ascx.cs class to derive from this

public partial class Ferret : BaseFerret
{}

3. Modify @Control directive in both user controls so that it additionally
contains

< % @Control ... CodeFileBaseClass="BaseFerret"  % >

4. Modify the code on Page to cast to the base type

      BaseFerret ctlFerret1 = (BaseFerret)LoadControl("Ferret1.ascx");

    ctlFerret1.DisplayFerret();

    plcVole.Controls.Add(ctlFerret1);

    BaseFerret ctlFerret2 = (BaseFerret)LoadControl("Ferret2.ascx");

    ctlFerret2.DisplayFerret();

    plcVole.Controls.Add(ctlFerret2);

Interesting, isn't it. With CodeFileBaseClass, you basically let the compilation system to know about the base class so that it won't generate fields for it. Otherwise you'd end either to null reference or casting problems as you'd have dynamically generated fields in partial classes while code in base class references its local member (which would have null reference, and eventually raises an exception).

Here's link to the relevant documentation:

@Control directive
http://msdn2.microsoft.com/en-us/library/d19c0t4b.aspx

@Page directive
http://msdn2.microsoft.com/en-us/library/ydy4x04a(VS.80).aspx

Edit: Scenario here is certainly bit artificial, since you could also create a property (and place a Label in the UC)  and just change the Text on Page via the property by instantiating the same user control twice (in Page's code-behind). CodeFileBaseClass does add complexity but I suppose it's real value comes with writing larger and deeper page/uc libraries. This was just good place to demonstrate it. :-)

Published Wednesday, March 08, 2006 9:58 PM by joteke
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments

Leave a Comment

(required) 
required 
(required) 
Enter the code you see below