views:

499

answers:

4

Hello,

If we want to convert a Page to user control then we should also do the following:

“If you aren’t using the code-behind model, make sure you still include a class name in the Control directive by supplying the ClassName attribute. This way, the web page that consumes the control can be strongly typed, which allows it to access properties and methods you’ve added to the control..”


I’m not sure I understand the above quote:

Namely, if we don’t use code behind class, then ascx class will derive directly from UserControl class! Thus if we don’t use code behind class, then there won’t be any methods or properties added to a control, so why would web page have problems accessing any of user control’s properties and methods? So why would we need to include a class name in Control directive?

thanx

+2  A: 

I think I should clarify how the compilation model works. First of all, you can write everything (including C# code) in a single .ascx file and inherit from whatever class you want to (that ultimately inherits from UserControl) by specifying Inherits attribute (or you might want to omit it) and without a ClassName attribute. If you do this, you can still access the properties from the .aspx file that uses this control. The thing is, you can't use the class in the codebehind file of .aspx page (if it has one) directly. By specifying the ClassName, if you are using the Website project model of Visual Studio, you can access it from the .aspx.cs file too. Note that this would not work in Web application project model as every .cs file will be compiled ahead of the time (prior to the .ascx file). In that case, even ClassName attribute wouldn't help much.

In any case, strictly none of the attributes are necessary. You can always use the properties defined anywhere in .ascx or .ascx.cs file included in a page in the .aspx file (but not always .aspx.cs file).

Edit to address the update to the question:

A) From your source code, it seems you are using the Website model here. Note that I mentioned you cannot use the class directly. I agree this statement might have been a little misleading. What I wanted to note is that without a ClassName, ASP.NET will choose a name for your user control class but that name is not guaranteed. While you can use the generated name, it's not recommended at all. You should treat it pretty much like an anonymous type where you can use an instance but cannot mention a name. In your example, you are basically referencing an instance (which is constructed on the .aspx markup), not the class, which is OK.

B) What you are saying is correct. Whatever you declare in ascx.cs in a Web application will be visible to .aspx.cs and .aspx. What I was talking about is properties that you declare in .ascx in a <script runat="server"> tag. Those will not be visible to .aspx.cs since it's compiled beforehand.

C) ASP.NET will generate the class defined by the ClassName attribute in the ASP namespace. You should use ASP.Some_Name instead. There is one thing I forgot to mention: in this case, you should somehow reference the .ascx in the .aspx markup; either with a Reference directive (<%@ Reference Control="MyControl.ascx" %>) directive or with a Register directive (<%@ Register TagPrefix="abc" TagName="xyz" Src="MyControl.ascx" %>). This will ensure that the ASP.NET build engine puts the generated .ascx class in the same assembly as .aspx page.

Mehrdad Afshari
+1  A: 

if we don’t use code behind class, then there won’t be any methods or properties added to a control, so why would web page have problems accessing any of user control’s properties and methods? So why would we need to include a class name in Control directive

  1. You can embed any code behind code in your .ascx/.aspx file, in new asp.net mvc model, there won't be any code behind by default. I think code behind is optional, it's just a nice way to separate one class into two pieces. Partial class is used in code behind.
  2. Even if you don't use code behind class, you can still inherited properties from base control. Then by declaring a class, you will be able to access those properties too.
J.W.
A: 

hello

I hope someone can help me with this, because I can't figure this out on my own no matter how much I try to:



A)

I think I should clarify how the compilation model works. First of all, you can write everything (including C# code) in a single .ascx file and inherit from whatever class you want to (that ultimately inherits from UserControl) by specifying Inherits attribute (or you might want to omit it) and without a ClassName attribute. If you do this, you can still access the properties from the .aspx file that uses this control. The thing is, you can't use the class in the codebehind file of .aspx page (if it has one) directly.

But why then was I still able to access UserControl’s properties from the aspx.cs file even without specifying ClassName attribute:

ascx file:

<%@ Control Language="C#" AutoEventWireup="true" 
CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl"%>

ascx.cs file:

public partial class WebUserControl : System.Web.UI.UserControl
{
public  string Some_Property
{
    get { return "this is UserControl "; }
}

aspx.cs file:

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = WebUserControl1.Some_Property; //works fine
    }
}



B)

By specifying the ClassName, if you are using the Website project model of Visual Studio, you can access it from the .aspx.cs file too. Note that this would not work in Web application project model as every .cs file will be compiled ahead of the time (prior to the .ascx file). In that case, even ClassName attribute wouldn't help much.

But doesn’t Web application project compile all code-behind files into a single dll? Thus if ascx uses code behind, won’t this ascx.cs also be compiled into same assembly as aspx.cs file? Thus shouldn’t we in that case be able to access the class from aspx.cs also ( provided we specified ClassName attribute )? But I was able to access UserControl’s properties from aspx.cs, even if I worked in Web application project ( and even though I didn’t specify ClassName attribute )?!



C) Besides, when I did specify ClassName=”Some_Name” attribute inside control directive, I wasn’t able to refer to Some_Name inside aspx.cs:

<%@ Control Language="C#" AutoEventWireup="true" 
CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" ClassName=”Some_Name”%>

Aspx.cs file:

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Some_Name some_name; // compile time error
    }
}

Could you tell me what I'm doing wrong?



thanx

SourceC
This should really be an edit to your question.
Zhaph - Ben Duguid
thanx, will remember that for the next time
SourceC
BTW - I only noticed this after I posted my last reply, else I would edit my previous post instead
SourceC
A: 

hello,

A) From your source code, it seems you are using the Website model here.

No, I was always using Web application project


Note that I mentioned you cannot use the class directly. I agree this statement might have been a little misleading. What I wanted to note is that without a ClassName, ASP.NET will choose a name for your user control class but that name is not guaranteed.

So user control is not of class type defined in ascx.cs, but instead user control’s type is derived from class defined in ascx.cs?


While you can use the generated name, it's not recommended at all. You should treat it pretty much like an anonymous type where you can use an instance but cannot mention a name.

  • So you are suggesting that even if I know what the type of UserControl is ( thus I know the generated name ), I still shouldn’t reference it? For security reasons?

  • But if I use ClassName attribute, then it’s perfectly safe to reference UserControl’s class?



C) ASP.NET will generate the class defined by the ClassName attribute in the ASP namespace. You should use ASP.Some_Name instead.

I tried it and still I get an error:

Ascx file:

<%@ Control Language="C#" AutoEventWireup="true" 
CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" ClassName=”Some_Name”%>


Aspx file:

<%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %>


Aspx.cs file:

public partial class _Default : System.Web.UI.Page
{

protected void Page_Load(object sender, EventArgs e)
{
    ASP.Some_Name some_name; // compile time error
}

}

I also tried adding “using ASP;” , but to no effect



I appreciate it

SourceC