Confusion with Root Namespace in Asp.net web project - asp.net

I have an VS2008 solution with 2 projects, WebUI and Domain; WebUI references domain
The Root Namespace in the WebUI project is:MyCompany.MyProjectName.WebUI
The Root Namespace in the Domain project is blank. (Namespaces are manually declared for all classes)
So everything has been working fine, until I tried to reference a class in Domain via a fully qualified path:
MyCompany.MyProjectName.Domain.EntityClasses.SomeClassName
VS was not able to find the class.
However, if I do at the top of the code file:
Imports MyCompany.MyProjectName.Domain.EntityClasses
....then it can see it. (Just as SomeClassname, not the fully qualified name)
Does this make any sense?
So, then I cleared my WebUI Root Namespace, and voila, the fully qualified declaration then does work. However, doing this then seemed to invalidate the registration of all my user controls on my pages. The only thing that seemed to solve this was in the codebehind of each user control, manually add a namespace of MyCompany.MyProjectName.WebUI
...which might make sense as perhaps the namespaces of the pages somehow had still retained the root namespace value. But, if I was to create a brand new aspx page and drop a user control on (this is before manually adding the namespace), even that page couldn't properly register it. Yet, the uwer control properly rendered in design view....so the VS UI seemed to be able to properly resolve it, but the compiler seemingly can't.
So from what I can tell, I can at least get things to work by manually wrapping user controls in the proper namespace. Why this is necessary for aspx pages, that have no namespace specified, to see the user controls, seems to make no sense.
Is there some fundamental principle I am misunderstanding??

Ok, I think this is the problem:
When you have a root namespace specified for your project and create a new aspx page, the aspx page will hardcode the root namespace in its definition at creation time, ie:
<%# Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/MasterPages/DefaultMasterPage.Master" CodeBehind="Home.aspx.vb" Inherits="yourCompany.yourApp.WebUI.Home" %>
...and that will never change even if you change the project root namespace. If you didn't have a root name space when the page was created, you'd get:
<%# Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/MasterPages/DefaultMasterPage.Master" CodeBehind="Home.aspx.vb" Inherits=".Home"
So if you change the root namespace half way through, all the prior aspx pages will have their namespace hardcoded to the old value. However, I think the code behind for the aspx does react to the removal of the root namespace, so you start to get weird behaviour with user controls, etc. and you have to go into all the code behinds and explicitly set a matching namespace in there for the pages to work properly. In this case, I think the best thing to do is search all your aspx files for this explicit definition of the namespace (in the Inherits tag) and remove it. You should, I think, still be able to explicitly set the namespace in the codebehind if you so choose, which the aspx will inherit. Not 100% sure though.
Long story short, decide which namespace naming method you want at the start and stick with it.

I would suggest you use the Web Application project format to avoid this kind of thing. Web Site projects are a retrograde move for anything other than simple sites.

Related

Type or namespace could not be found only on a publish

I have a web solution with Visual Studio 2010 and ASP.Net 4.0. In this solution there is a web site as well as a class library.
I added a new User Control to the site and was able to build everything. I was even able to publish with the new control. The issue arises when I try to reference the class name of that control in a different part of code. When I do this, I still am able to build / rebuild the entire solution. But when I try to publish, I get the error "type or namespace name could not be found."
When we publish, we always UNCHECK the box "Allow this precompiled site to be updatable" and we always CHECK the box "Use fixed naming and single page assemblies."
If I do a publish and UNCHECK the box "Use fixed naming and single page assemblies" it will publish just fine. But for some reason I can not get it to publish with that box CHECKED which is what I need to be able to do.
I have tried:
Cleaning the solution
Restarting Visual Studio
Restarting Computer
Clearing out .net temp files folder
Recreating the control
Putting everything in website into a namespace
Any help or insight would be greatly appreciated.
Thanks.
EDIT:
I figured it out. I was adding this new control dynamically. But I didn't realize it also needed registered on the page that I am using it on. After registering the control, everything worked as expected
When you want to use your web user control dynamically, as you use other .net controls like textbox, label etc. you need to follow these steps.
(1) Add a ClassName property in your control directive as below (in ascx file)
<%# Control Language="C#" AutoEventWireup="true" CodeFile="CustomControl.ascx.cs"
Inherits="CustomControl" ClassName="CustomControl" %>
Note : Make sure the ClassName & Inherits both are same as class name in the CS file.
(2) Add a Reference directive on the page where you want to use your web user control dynamically
<%# Reference Control="~/usercontrol/CustomControl.ascx" %>
Note : Reference directive is different then Register directive.
(3) Now you can add your user control dynamically anywhere on your page like below
ASP.CustomControl cuCtrl = (ASP.CustomControl)LoadControl("~/usercontrol/CustomControl.ascx");
//add dynamically created custom control to an existing panel or any container control on your page
pnlDemo.Controls.Add(cuCtrl);
Note : You can always include the ASP namespace in the using ;)
After this, you should not face any problem publishing even when checking the Allow this precomplied site to be updatable option.
I figured it out. I was adding this new control dynamically. But I didn't realize it also needed registered on the page that I am using it on. After registering the control, everything worked as expected.
I tried that and still have the same problem when publishing, either with reference tag or register tag it doesn't publish. Only way to work by now is to uncheck the "updatable site"

How are custom controls instantiated in asp.net?

My understanding is that when a component or custom control is defined in an aspx page using the <%Register%> tag, it is declared in an auto-generated designer.cs (C#) file by the compiler. If this custom control is never used in the aspx page, does this still happen in the designer.cs file?
Assuming the control is used in the aspx page, what mechanism then instantiates this control, how is it new-ed up behind the scenes? The designer file only declares it. Thanks much, and if there are good articles out there discussing this I’d be happy to read them.
This may not answer all your questions, but some of them. Rick Strahl wrote a great article a while back on compilation and deployment that describes how it works:
Compilation and Deployment in ASP.NET 2.0
I added part of the article that I think relates most to your question below:
Referencing other Pages and Controls
Remember that page and control compilation happens on a per directory basis! So referencing other pages and controls becomes a little more tricky for ASP.NET 2.0, because you can no longer assume that a CodeBeside class from another page or control is available in the current assembly. At best all pages and controls in the same directory end up in the same assembly, at worst each page or control gets its own assembly and they know nothing about each other.
If you need to reference another page from a control or another page you need to explicitly import it with the #Reference directive. Again this is different than ASP.NET 1.1 where all CodeBehind classes were immediately available to your entire Web application. In ASP.NET 2.0 an explicit assembly reference is required to load it.
Assume for a minute that you have the DataEntry.aspx page I showed earlier and you want to create a second page that uses the same CodeBeside class so you can reuse the page logic, but change the page layout in DataEntry2.aspx by changing a few colors and moving around the controls of the page. In essence you want to have two ASPX pages reference the same CodeBeside file.
Here’s how to do this:
<%# Reference Page="~/DataEntry.aspx" %>
<%# Page Language="C#" AutoEventWireup="true" Inherits="DataEntry" %>
I’m leaving out the CodeFile attribute reference the CodeBeside class of the DataEntry page, and add the #Reference tag to the page to force the CodeBeside class to be imported.
The same is true with any User Control definitions. To import a user control you need to use the #Register tag, which imports the assembly that the control lives in. ASP.NET is smart during compilation and figures out exactly where related assemblies live based on how the project is compiled. If the control or page lives in the same assembly no reference is actually added. But if it is external – in another directory for example, then the assembly reference is added.
Referencing problems
If you can explicitly reference other pages and controls in your markup pages, then all works well and as expected. But if you dynamically load controls or reference pages dynamically in your code, things get a lot more complicated.
The most common problem I run into is dynamic loading of controls. In ASP.NET 1.x you might have run code like this for dynamically loading controls into a page:
public partial class DynamicControlLoading : System.Web.UI.Page
{
protected CustomUserControl MessageDisplay = null;
protected void Page_Load(object sender, EventArgs e)
{
MessageDisplay = this.LoadControl( "~/UserControls/CustomUserControl.ascx") as CustomUserControl;
this.Controls.Add(MessageDisplay);
}
protected void btnSay_Click(object sender, EventArgs e)
{
this.MessageDisplay.ShowMessage(this.txtMessage.Text);
}
}
CustomUserControl in this case is a simple User Control that lives in another directory and is loaded dynamically at runtime. Further assume that you truly dynamically want to load this control so you may have a choice of several controls, or the end-user might even create a custom control that gets dropped into place instead.
If you run the code above in ASP.NET 2.0 it will likely fail. I say likely because there are some inconsistencies that will sometimes pick up control references automatically, for example if the user control lives in the same directory and gets compiled into the same assembly as the page, or if another page has the control referenced.
It should and usually will fail. Why? Because ASP.NET compiles on a directory level and the CustomUserControl lives in a separate directory and so goes into a separate assembly. It’s not visible to page class to get a strongly typed reference. Intellisense will show a big, fat and red exclamation point or nothing at all for the MessageDisplay control. When you run the page it will bomb.
You can reference the control as the Control type of course, but if you need to access any custom properties on the user control beyond Control properties you can’t unless you resort to Reflection. As far as I know there’s no way to add a reference to another user control or page programmatically because the reference needs to be available way earlier at compile time before your code ever runs.
Alternatives are to not load controls dynamically or at least provide some mechanism to load up any user controls beforehand on a page with the appropriate #Register tags. But that’s not always possible. The other option is to create a user control base class in APP_CODE and expose the public interface there. The main problem with this is that this base class will not have access to any internal controls of the user control and so the base class would have to use FindControl to reference any embedded controls. So this is inefficient as hell, and cumbersome to boot.
I’ve run into similar situations with inheritance scenarios. For example, inheriting one master page off another’s CodeBeside class. All works well, but the ASP.NET compiler complains that the Profile object is being overridden illegally (a compiler warning). Running with the inherited master page works, but there are quirks. User Controls added to the master page often fail with type conflicts as ASP.NET treats the user control added to the base page as a different type than the user control added to the second page.
It’s inconsistencies like these that deal with referencing other types that have made me waste an incredible amount of time, thinking I had something fixed only to find out later that it didn’t actually work consistently when I changed a completely different page. Worse you have to really understand the model to get your head around what might be wrong.
Bottom line: The overall ASP.NET 2.0 compilation model is internally complex. Most of the time you don’t need to understand it, but when you run into these boundary scenarios, you really DO have to understand what goes on behind the scenes to be able to work around the quirks.

LoadControl(string) in different assembly?

I'm developing a stand-alone ASP .NET component for dropping in to various sites we create.
Part of the application is a CompositeControl, which needs to load a UserControl.
However, CompositeControl has no LoadControl() method - in stead, I must (as far as I can see?) rely on Page.LoadControl() and this is a problem!
How do I know the path to my control, when the page is not part of the assembly?
The page the CompositeControl is situated on resides outside the assembly I am writing the Page.LoadControl() code in, and thus cannot find my .ascx file.
I've tried LoadControl(type, object[]) but this doesn't load the "code infront" file, which I need.
So - how do I find the Path to some .ascx file inside some included assembly (name known, ofc) for my Page.LoadControl? Or, alternatively, is there some other way to load the control from inside the CompositeControl?
Cheers!
EDIT:
The following provided the solution, although it is slightly hacky. It does work, however:
http://www.cmswire.com/cms/tips-tricks/aspnet-reusing-web-user-controls-and-forms-000915.php
This may be of some help to you : http://blogs.msdn.com/b/davidebb/archive/2005/10/30/487160.aspx

Ambiguous Reference

In my WAP project, every .aspx's code-behind and designer share the same namespace. For example my Main.Master.cs and Main.designer.cs are both in the OurCompany.Web namespace by default.
When I go to another .aspx page and use the following, I get an "Ambiguous reference" error because it can't decide if I'm talking about my code-behind or designer file of that master page
<%# MasterType TypeName="OurCompany.Web.Main" %>
but by default this is the way VS creates .aspx pages so should I really care?
The designer files are all marked as "partial" classes so they don't get compiled into their own types.
My guess is that you really do have 2 classes called "OurCompany.Web.Main". A tool like Reflector would let you browser your DLLs so you could tell for sure.
This just happened to me, your problem is the JIT compilation creating temporary "copies" of your assemblies in a temp directory.
Make sure every namespace/partial class declaration is "tight", check for incorrect class names, wrong namespaces.
The problem "just went away" for me as well. Recreating or cleaning the solution will probably do it. Wish I could be more helpful but going cleaning up the source, both manually and with the right click menu probably helped.
I'm guessing you have a master page and a web form page with the same name on the code behind class. And this will prevent your site from working correctly (if it works at all).
I'd go through my aspx.cs files and looking for the class name main (find should work here). I bet you will find two files with the name. You will have to change one of them to something else. Just make sure you also change the Inherits in the .aspx page and the .designer.cs class name.

User Controls Not seeing the Day of Light - Doesn't recognize code-behind methods

This is driving me absolutely nuts.
I created a new WAP project in VS 2008. Copied over the files in my Web Site Project. Added any required references. Tried to convert the Web Project to a Web Application using the "Convert to web application".
None of my user controls are able to see methods in their code behind. They don't even see them so I get errors everywhere saying it doesn't know what this or that method is.
Example:
<%=CreateMenu(xxx.WebMenuType.Occasion, "menuShopOccasion", "Occasion") %>;
That is in my Header.ascx
And so it errors out because it has no clue what CreateMenu is!
In my Header.ascx.cs it's there and was being referenced with no problem in my old Web Site Project:
protected string CreateMenu(xxx.WebMenuType menuType, string menuID, string title)
{
...
}
It's probably a namespace problem. Make sure that the Inherits attribute in your <%# Page ... %> declaration refers to the correct path to the code behind file, including the namespace. The designer file must also be in the same namespace as the code behind.
I am not entirely sure this is your problem but....
you may be missing the .designer.cs files. For your example above there would also be a Header.ascx.designer.cs which contains a partial class (Header) which has all the declarations of the controls in the Header.ascx file?

Resources