locked
Pre-compilation anywhere RRS feed

  • Question

  • User-1415508811 posted
    Hi All! I'v created some UserControls in *.ascx files in my VS 2005 web site project. Also I'v created some classes in /Code/*.cs files in site folder that need to use early creaded usercontrols. But when I start compilation the next error have procesed: "error CS0234: The type or namespace name 'Blablabla' does not exist in the namespace 'MySite.MyUserContrls' (are you missing an assembly reference?)" After this I'v started aspnet_compile utility for creating full precompilation of *.as*x files and processed same error, because this utility compile site in two steps and compile class library files first. Can I use one-step precompilation of my site? Or I need to write extreaml MSBuild pre-compilation script, or need to re-design my site architecture? Thanks for all
    Wednesday, March 9, 2005 9:36 AM

All replies

  • User-34549978 posted
    I need more information. Asp.Net will build the code folder and pass the resultiing assembly as a reference to each page\user control it needs to build. Where is the namespace it is complaining about defined?
    Thursday, March 31, 2005 6:03 PM
  • User-1653776603 posted

    The compilation for asp.net 2.0 compiles the code directory before the pages/controls. This means that you will have a problem if you are trying to refer to the controls from within the contents of the code directory.

    How much of the control do you need to reference from code. One [hacky] answer would be to create a base class in the code directory for each control you need to reference, and put the properties/methods you need in that base class. You can then use that base class for the control, and override the properties/methods as necessary.

    Sam

    Monday, April 4, 2005 1:36 PM
  • User-2105694027 posted

    I have the same problem.  I have classes that I used to just toss in a folder (_Classes).  These were "facade" level classes that needed to live in the web application project since they needed access to session, etc.  I also had some helper methods that would do things like take data in and out of user controls. 

    The problem now is that my pages don't seem able to reference these classes unless I put them in the app_code folder.  Once I put them there, however, they can no longer reference the user controls.  I seem to be in a catch22. 

    I'm sure I can learn to deal and even appreciate the new design, but all the articles I keep reading start off with "ASP.NET 2.0 is 100% backwards compatible."  However, with issues such as these, I find myself with a huge amount of refactoring before I can proceed forward. 

    What am I missing?

    Monday, May 16, 2005 7:10 PM
  • User-1394831673 posted

    VS03 compiled all content pages (webform, controls) into one assembly; VS05 compiles each content page (along with its code-behind if there) into its own assembly. As a result, code in the App_Code folder cannot access the page anymore, so you get a broken reference.

    Sam mentioned a workaround for this situation. You need to create an abstract base class for the control in the App_Code folder (lets call this the stub file). This will allow your code to compile (since it can find the reference in App_Code) and allows the runtime to do a late binding to your real control (outside of App_Code).

    For example, lets assume you have the following (where C1 and C2 are controls, and S1 is a standalone code file):

    V1 App:
    AppRoot

      
    C1.ascx      // inherits=”C1”
      C1.ascx.cs   // class C1 : System.Web.UI.Page { public void foo() {} }
      C2.ascx
      C2.ascx.cs   // C1 myC1 = (C1)LoadControl(“C1.ascx”)
      S1.cs      // instantiates an C1 object which calls foo()

    V2 App:
    AppRoot
      C1.ascx      // inherits=”mod_C1”
      C1.ascx.cs   // class mod_C1 : C1 { override public void foo() {} }
      C2.ascx
      C2.ascx.cs   // works since it will call the stub file
      App_Code
        stub_C1.ascx.cs   
        // abstract class C1 : System.Web.UI.Page { 
        //   abstract public void foo(); }      
        S1.cs      // works since it will call the stub file

    Things to note:

    1. File names and class names do not have to match. Hence the stub file contains the original class name "C1" and the referenced control has a modified class name "mod_C1" (and has C1 as a base class). You actually can keep the same file name in App_Code, but I prefer to show it is a stub by naming the file explicitly that way.
    2. This naming means you don't have to change the referencing/calling page or control, since it will still refer to the original class name (which is now in the stub).
    3. Not all controls need a stub file, just those controls which are referenced by another control. Hence C2 did not need a stub file, since no other page is referencing that control.
    4. This approach should work in most cases, but there are probably edge cases where it may fail. For example, an abstract class cannot be instanciated so if your code does this it is going to fail. You might try using a normal base class rather than an abstract base class at that point.

    I hope that helps; I wish it could be easier.

    Tuesday, May 17, 2005 3:12 PM
  • User-1394831673 posted

    Ignore this.

    Tuesday, May 17, 2005 3:17 PM
  • User-1394831673 posted
    Doh. I wanted to set the option to "Email me replies to this post" so I wrote a one-line to ignore my little post to set the option (not to ignore the big post I just did). Sorry about the confusion...
    Tuesday, May 17, 2005 3:19 PM
  • User1622957740 posted

    While this work around may work in some scenerios it's a really bad idea for pages that are complex and contain lots of controls. What you suggest gives access to the underlying base class and methods, but it really makes it even harder than it already was to access controls on page.

    This basically blows even the limited 'visual inheritance' mechanism that VS 2003 had away. The only way you can access controls now is with FindControl, which is inefficient and prone to errors as it lacks strong type support.

    It seems to me there should be some way to consolidate this. Master Pages appear to be globally visible - they have to be - so why not pages in the same way (MasterPages and controls appear to compile into separate assemblies).

    IMHO, this is a big problem for a number of applications especially ported applications. Just about all of my apps did some of this for their templating/theming support or merely providing some limited visual inheritance. All that is broken and needs manual fix up.

     

    Monday, May 23, 2005 3:50 PM
  • User-1394831673 posted

    You raise a good point. Using a stub class is not a recommended practice for new applications -- my post is really meant to help ASP.NET 1.x developers port their web apps to 2.0 more quickly. A new web app should use the appropriate attribute tag to explicitly reference another user control.

    Master pages and user controls are similar in level of access, i.e. master pages are not globally visable so you have to use an attribute to find the master page too.

    We realize that cross-referenced user controls are a migration issue and are working on ways of improving our migration in this area. In the meantime, hopefully the workaround posted here will help early adopters.

    Monday, May 23, 2005 4:36 PM
  • User1622957740 posted

    Hmmm... maybe I'm missing something, but I CAN see master pages in Intellisense and I CAN reference them in code without problem.

    This has to be this way since you are passing Page.Master back and we need to be able to cast the Master page to a specific page. The following works for me in a content page:

    SiteMaster ParentPage = this.Master as SiteMaster ;

    ParentPage.PageTitle = "West Wind Articles Archive";

    Note that I can cast to SiteMaster here so the Master Page IS visible to other pages. Since Masters are really just custom controls using the same partial class compilation model this same sort thing ought to be possible with Page classes.

    +++ Rick ---

     

    Monday, May 23, 2005 5:30 PM
  • User-813747361 posted
    So how do you suggest we do this in 2.0 (I have the problem but not in a migrated project).  I have a page where I want to load controls dynamically, but making sure I have a <% reference %> in the page as well as in the codebehind seems asinine to me.  Its not about backwards compatibility, but assembly generation.  Is one assembly per page the only way to do it?  I expect to deploy the site as a single file, why can't I debug it this way?
    Friday, September 23, 2005 7:14 PM
  • User1622957740 posted
    I have no idea how this should work either and unfortunately contrarty to Michaels post that seems to imply that MS was still working on this, the behavior has not changed all the way up to the RC now.

    There are a number of people who've major issues with this - especially people with frameworks (like DotNetNuke) which rely almost exclusively on dynamically loaded controls that they can now no longer access.

    The only workaround I see is to implement a base class and casting to that as I mentioned earlier in the thread. This is really not a heck of a lot better than the explicit <%@Register tag as it means that you can't do this generically. And in some cases it's not possible to inject into the class hierarchy if the control is previously subclassed.

    It sucks - this is IMHO a major oversight and design flaw in ASP.NET 2.0... they've taken away a very powerful feature for the sake of simplicity in the compiler model, which is not worth the the trade off. Worst of all there could have been ways to fix this by having the compiler provide a more comprehensive mechanism for associating assemblies or still providing single assembly compilation...

    Oh well, now we're stuck with it...

    Friday, September 23, 2005 8:15 PM
  • User-1394831673 posted

    The change to use multiple assemblies is just one of many changes in the web project system to improve performance and make it easier to develop web apps. If you have not done so already, you should check out ScottGu's blog post on the subject at http://weblogs.asp.net/scottgu/archive/2005/08/21/423201.aspx 

    Thanks,

    Monday, September 26, 2005 11:54 AM
  • User-813747361 posted
    I've been told the "performance improvement", but since no compilation is happening at runtime in most large sites, I don't see multiple assemblies as being a performance improvement.  Perhaps at development time.  (I have read on Scotts blog about a new tool to allow compilation to a single assembly for deployment.)

    But to understand what you said, how does multiple assemblies help "make it easier to develop web apps"?  Easier for the ASP set who want do drop their code on a server and have it auto-compile, sure.  But again, for most enterprise-sized applications this is a security risk and encourages the black days of developers having access to the web servers to fix issues.  This certainly feels like a step backwards, not forwards.
    Monday, September 26, 2005 3:59 PM
  • User1622957740 posted

    Michael,

    With all due respect to Scott, but what Scott describes in that post is a hack! It's a workaround for a design problem that many people have pointed out very early on in the product cycle and have been ignored by the ASP.NET team.What's interesting to me is that the people that are complaining about this most are many of the gurus who supposedly know how to take best advantage of the tool - that's always a bad sign when your most loyal supporters end up being the loudest for criticizing a feature.

    This isn't the last you're going to hear about this problem either - once ASP.NET ships and more developers will actually build real applications with it you will see many more developers run into this issue.

    Part of the problem too is that even for new development this will be a huge issue, because once you get to the point where you need to dynamically drop controls there aren't a whole lot of workable options to do it and you're stuck.

    +++ Rick ---

    Monday, September 26, 2005 5:42 PM
  • User-1394831673 posted

    My apologies for not being clear. I meant the set of VS05 web project changes (not just the use of multiple assemblies) allow easier web development as well as performance improvements. The URL I posted was for Scott's justification of that statement.

    Thanks,

    Monday, September 26, 2005 5:51 PM
  • User-813747361 posted
    I agree with Rick.  My problem with it is *not* a migration issue...  I am working on a new site and the <% VirtualReference %> idea seems to be hacky, and the idea of a post-build step to build into a single assembly is a hack.  I understand the motivation for this *feature* but it should be an option, not the default (IMHO).
    Monday, September 26, 2005 6:05 PM
  • User2048810428 posted
    I'm currently developing a large site and I can tell you that the "performance gains" of multiple assemblies is not as great as advertised.  We currently have about twenty directories and some of them have upwards of 50 aspx pages.  Each page typically has a databound grid view, two databound edit views and at times 1 - 10 child grid views on a detail view.  With the amount of data that we display on the application, a CRM application for Auto Dealerships, compile times have become a problem even with the new enhancements. 

    Our experience has shown that the compiler is very picky about which files have been touched and how they affect other files.  This is perhaps a result of all the app_Code classes that make up our business layer being compiled into one assembly.  Touch the a single file in that directory and the entire application recompiles. 

    Our editing has show sporadic support for editing on the fly.  Often times a single attribute change to the markup of an aspx page causes the entire application to recompile which at this point forces the rerun of the application to timeout.  It would be nice if the built-in web server preserved sessions state and httpcontext while the compiler was working its magic.  As of now we end up recompiling about once every three changes to a page.  Code behind changes increase the rate of site recompile and touching anything common invalidates the entire common layer.(i.e. app_Code, app_Themes, master pages, bin dlls)

    At this time, I'm not convinced there is a big performance improvement over the old 1.1 way of doing things.  On paper, sure and in marketing yes it is there but in the real world its just not as visible.  A small upgrade in developer ease really. 

    Derek Licciardi

    Tuesday, September 27, 2005 7:51 PM
  • User-1760333648 posted

    To avoid hardcoding URL's and querystring parameters in my pages I would often add static methods with parameters to a page.  For example, ShowCustomerDetails(customerID As Integet) which returned a Url with query string parameters ("/CustomerDetails.aspx?customerID=123").  This allowed standard interfaces to be developed between pages.  I'd use the static method to set the NavigateUrl of hyperlinks, etc.  I was quite pleased with this solution as it allowed type safety of parameters and allowed parameter names, default values, etc to change without touching any referencing pages.

    As 2 pages can no longer 'see' each other this is now broken in Net 2.0.  This is just another example of the pain which is the new compilation model.

    The ASP team can give us any number of workarounds to the new problems introduced but the fact is they are problems which should have never been created.  I've read ScottGu's justification of the changes and the removal of the web project file but the fact is I'm not seeing any of the perceived benefits, just being frustrated at the things which no longer work in 2.0.

    Time and time again, we're seeing MVPs and other experts in the community criticse the new model but the ASP team don't seem to want to listen.  Where are all the advocates of the new model?  I certainly don't see any outise the ASP team.

    The new features in Whidbey bring a huge amount to the ASP web platform but the changes to the compilation model/lack of a project file seem to be a huge step backwards.

    Monday, October 10, 2005 7:57 AM
  • User-1394831673 posted
    Just checking, but wouldn't adding a Reference directive to your aspx page allow your static method to work (I assume this is a code-behind to code-behind reference)? If so, it seems like a simple fix (and one that is usually caught and fixed by the latest web project migration wizard).
    Friday, October 14, 2005 2:41 PM
  • User-1760333648 posted
    Yeah, in my case adding a reference to each page would solve the problem but it doesn't feel like the right thing to do.  This is not an application I'm migrating either but it's a model which I found worked in NET 1.x.  It feels awkward to insert and maintain a list of references in every page.  As you'll appreciate, if I need to generate links to 10 different pages using my technique, I will be required to reference each of the 10 pages.  This just worked in NET 1.x.

    This is a breaking change between framework versions and I'd hope there was some way to maintain the previous (single assembly) behaviour.  Can anyone tell me if there is a way to do this?  I suspect not as we no longer have web project files and several other people seem to have ran into problems setting default namespaces, etc.
    Monday, October 17, 2005 4:05 AM
  • User-1394831673 posted

    AFAIK, there is no way to do this with VS05 or ASP.NET 2.0.

    Monday, October 17, 2005 1:27 PM
  • User-1394831673 posted
    I just re-read what I posted and I should have been more clear. AFAIK, there is no way to maintain a single assembly compilation model with VS05 and ASP.NET 2.0 that I know of.
    Monday, October 17, 2005 1:28 PM
  • User1524416148 posted
    I am one of those peopel that like how .net 2 works.

    Most of my web forms don't need to talk to each other. If they do, all they need to do is pass a number, which is easy to send on a query string and validate. This also makes the queries bookmarkable, which makes the application user friendly.

    The separate assembles method is similar to how the open source industry works: do one thing well and pass the result to next in line by script. This is the best way to look at web applications, since that is how the end user sees them. When a user ccomes to a 50 page site, he/she sees 50 different and separate applications, not one, and will treat the site as 50 applications. Writing web sites to conform to this mentality makes for faster applications.

    Some of the applicaiton I read from posts on thsi site sound like they are in serious need of redesign. They seem to designed as Windows programs, which doesn't cut it a cross-platform environment such as the internet.
    Saturday, October 22, 2005 4:27 AM
  • User1622957740 posted
    No offense Meson, but you're missing the point.

    This has nothing to do with what the user sees. This has to do with architectual issues of how an application is built - not an external way to redirect to other pages. Some applications, like portals and CRM systems specifically require that components are loaded dynamically, and this has nothing to do with how users navigate to a particular page or what the URL looks like. What it has to do with is how the content of that page is loaded and that's what this thread and the complaints are about... specifically since this behavior has changed and has broken a common usage pattern for many developers.

    +++ Rick ---
    Saturday, October 22, 2005 3:55 PM
  • User418135331 posted

    I've spent the last 3 days on this and I really don't see a workaround. Our architecture requires that you dynamically load UserControls. This seems to work only if the master page knows about the child control.

    I've got a simple set of projects that doesn't work that has me absolutely astounded:

    Here's the issue, takes me about 2 mins to reproduce:

    - I have a terribly simple project called Master that is a web project.

    - I have a subproject in a subfolder of Master called "subproject"

    - The subproject has a control named "ChildControl.ascx"

    In the master project's single page (Default) I have this code:

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

    protected void Page_Load(object sender, EventArgs e)

    {

    UserControl uc = (UserControl)LoadControl("subproject/ChildControl.ascx");

    }

    }

    In the subproject's ChildControl.ascx I have this code:

    public partial class ChildControl : System.Web.UI.UserControl {

    protected void Page_Load(object sender, EventArgs e)

    {

    string x = SharedCode.SayHello();

    }

    }

    In the subproject I also have a class with a single static method called SayHello(). This class is in the App_Code folder of subproject.

    When I run this project, I get this error:

    Compiler Error Message: CS0103: The name 'SharedCode' does not exist in the current context

    But of course it DOES EXIST.

    I can't believe that this isn't possible. All I want to do is to use code IN THE SAME PROJECT (ChildControl's App_Code folder) with a static method.

     

    Thursday, December 1, 2005 7:34 PM
  • User-729062814 posted

    I think the problem you're runing into is with the sub project.  Web Site projects in VS05 represent an entire site.  You can have sub-webs but they must really sub-webs in the IIS metabase not just a sub-projects.  The App_Code folder is a special ASP.Net 2.0 folder that can only exists at the root of a Web Site applicaiton.  It is similar to bin in that way.  The class form the sub projects App_Code folder is never being compiled by ASP.Net.

    To work around this you can either move the class from the sub-project App_Code folder to the root App_Code folder or setup the sub-project as sub-web in the IIS metabase.

    Hope this helps, Brad.

     

    Friday, December 2, 2005 2:02 PM