Friday, July 31, 2009

App_Code folder doesn’t work with Web Application Projects (WAPs)

As you might already know we have two different project types for web development  in Visual Studio 1.) Web Application Projects (WAPs) 2.) Web Site Projects (WSPs)…

Often time developers hear that if you want to put a random class file in your web project you should put it in App_Code folder.  While this is true for Web Site Projects (WSPs), it is not so much true for Web Application Projects (WAPs) and in this post I will try to explain the inner workings on why that is the case…

Firstly App_Code folder is a special ASP.NET RUNTIME folder…  Any files in this folder are compiled by ASP.NET when your site is actually running on the server...  This essentially allows you to drop random class/code files in this folder to be compiled on the server side…  For this very reason if you drop something new into the App_Code folder of your running web site, it is like resetting it coz ASP.NET runtime now recognizes that there is a new class which needs to be kept in consideration during running the site…  This magical folder brings with itself various connotations when it comes to different project types…

First of all it is important to know that Visual Studio does not really create any DLLs when you are using Web Site Projects (even when you are building the web site)…  VS simply validates that your code is correct in WSP… In Web Application Projects (WAPs) this is not actually true as VS actually creates a DLL with all the code behind and class files that are present in your project and drops them into the BIN folder of your project…

In case of WAPs every file in the project is marked with a specific “Build Action” as shown below:

image

All the class files (.vb/.cs) are marked as “Compile”… This essentially tells VS to take all those files and call the correct VB/C# compilers on them…  The result of that activity is the DLL,which is named same as your project name i.e. WebApplication1.dll, being created in the BIN folder of your project…

With this understanding let us look at right click Add—> Add ASP.NET Folder --> options on Web Application Project

image

You will notice that App_Code folder is not really available as an option… This is an intentional behavior… 

If you add a App_Code folder into a Web Application Project and add classes to that folder then more than likely their “Build Action” will be marked as “Compile” (as all .vb/.cs files are defaulted to “Compile”)… This will signal Visual Studio to compile them inside the IDE to produce the DLL in the BIN folder…  For illustration let us assume you added a class called Products in App_Code\Products.cs file which is marked as “Compile”… Now when you build your WAP you will get a DLL in your project BIN (e.g. WebApplication1.dll), which when you open in ILDASM or Reflector will tell you that Product class exists in it…

Now when you try to run the project locally or do a xCopy deployment of your WAP to the server you will might accidentally move the App_Code\Products.cs on the server as well…  This is time when things start getting tricky… Now you have a DLL in the BIN which is provided as a reference to ASP.NET runtime which has the Products class… Also ASP.NET is trying to compile your App_Code folder (as it is a special Runtime folder and that is an expected behavior) which will result in duplicate declaration of your Product class (one in the referenced project DLL and second in the dynamic compilation)…  As you can imagine duplicate declaration of same type is not desirable…:-)

Additionally, VS will auto generate namespace for your Products class in the DLL to be something like WebApplication1.App_Code.Products vs ASP.NET runtime will produce a hashed version of the name space causing additional connotations giving you weird error messages…

So at a high level there are many reasons why App_Code folder is not supported for Web Application Projects and should be avoided…

Does this mean App_Code and WAPs just don’t ever work together?

No, that is not true… App_Code and WAPs can work together, you need to make sure that “Build Action” of none of the files in the App_Code folder is marked as “Compile”… Ideally you should mark them as “Content” which will ensure that they will get deployed on the destination and get compiled by ASP.NET instead of locally by VS IDE… 

But this will bring its own side effects that intellisense may not work very well for these files inside VS as they will not be treated as Class files by VS… But the key point is that you do not really need “App_Code in Web Application Projects (WAP) if you do not intend to put random code files or modify existing code files in App_Code folder directly on your production server…

What should one do if there are isolated code files which need to be added to WAPs?

You can add code files under any folder call it “CodeFolder”, “Controllers” or anything that makes sense in your project… Just avoid putting them under “App_Code” unless you specifically want the server side compilation behavior…

-Vishal

45 comments:

Amin said...

So Vishal what should we do then.. I've made expressionbuilderidentity.cs in vs2005.It's can run in VS but when put into web, it's create error (couldn't load assembly ....). I'm stuck..

Vishal R Joshi said...

Amin, as long as you place the class in any other folder than App_Code it should work fine... Is the assembly which is not getting loaded your ProjectName.dll? (i.e your WAP assembly?)

Amin said...

Hi, I'd already transfer my WEP to WAP and build. The folder App_Code now changed to Old_App_Code, BUT no dll file generated in bin directory. If we changed the App_Code folder to others name, how we call the class in web.config?

add expressionPrefix="UserIdentity"
type="ExpressionBuilderIdentity"/>


I'm using customexpression builder to get current username to view their profile.

Actually, I'm using asp.net application in Sharepoint for custom user profile due to so much limitation on sharepoint FBA.

Vishal R Joshi said...

Is your classes' Build Action marked as "Compile"... If you have your class marked as compile, it should get compiled as part of your project DLL and will not be created in a seperate DLL... The project DLL lies in the BIN directory and should be accessible within the web.config...
Are you finding no DLLs at all in your BIN directory?

Cameron Larson said...

After years of making websites I am making my first web project. I wanted to make a shared folder and so I created a App_Code folder like I saw in numerous Google search results. First clue something was wrong was that Intellisense didn't work, then I found this post. Thanks for the info, now I know. It seems like there should be more clear guidance on this, like a specific different place to put shared code that is not called App_Code, or make it impossible to add a App_Code folder to a project. Coding web projects is different than websites, I think I am going to learn every pitfall the hard way.

Vishal R Joshi said...

Cameron,
Even though it feels that you will face a lot of trouble along the way, I do not think you really will... If you do then do not hesitate to drop in a comment or send me an email and I will try to help as much as I can..
best luck...
-Vishal

Josh Blair said...

VRJ, I have a WAP that does not have an App_Code folder. I'm trying to add some class files in another language and want to use the codeSubDirectories element under the compilation section to denote the use of another language but it isn't working. Any recommendations? Thanks.

Vishal R Joshi said...

Josh, can you clarify whether you are trying to mix VB and C# in the same project...

James Gaisford said...

Just spent ages getting myself in knots using an app_code folder in a WPA. Thanks for the article. Really helped me out of a hole!

Anonymous said...

Vishal, Very very good article .. and you just saved my life.. i was going to put my class in App_Code(yes, its WAP) and now i hesitate.. any other recomendations? Should i just create new folder for allthe class files and use it accodring? Please let me know your opinion.

Thanks,
Smitha

rtpHarry said...

Wouldn't the best option in this case to put them in a separate class library and reference them in your WAP?

Anonymous said...

Hello Vishal,

Subject line - When we make a change to any file in App_Code folder website stalls-out


Here are some particulars -
We are using asp.net on our web server for about 2-3 years now. Web server uses IIS version 6. MS Visual Studio 2005 (we will change to 2008 in a couple of weeks). Our test server - which mirrors our production server is already on Visual Studio 2008.

Nearly all of our Datasets are stored in app_code folder, there are currently 60 files in this folder (.xsd, .vb and one .cd file). Some dataset files may have as many as 20 queries in them (exception, not rule), most of our site is database driven(SQL).

Our thinking was to follow conventional suggestions in putting all sql queries in app_code folder so that they are available throughout the site. When we converted from .asp to .Net all literature I read advised to put all datasets in app_code folder, which we did. Some pages we would hard-code the connections on the page-behind but for the most part we opted for app_code folder.

But as time wore on we finally realized the correlation to our site running slowly when we would make any update to the app_code folder. In order to rectify the problem I have to go to the IIS Services manager and stop ISS and WWW, then restart them. This does seem to work but it is a terrible way to have to run a website.

I've searched and searched but cannot come up with a solution (other than removing files from app_code folder) which at this stage is not an option.

Any help, suggestion, hypothetical theory you could come up with would be greatly appreciated.

Woodley Westbrook
wwestbrook@appraisalinstitute.org
312.335.4452

Anonymous said...

Vishal
likewise that Josh asked;
I am trying to mix VB and C# in the same project; but this without an app_code folder.
My project is a Vb WAP and I want to include a C# class in some folder like your example "CodeFolder”, But My class is not recognized for the compiler. I don't know what is the right way to do this.
Do you have any idea about this or link what it could help me.

Thanks

ALberto Guerrero Zaro.

Anonymous said...

Thanks! I had only been working with WSP until recently. Then I started using WAP and suddenly I couldn't access app_code classes and now I know why!

Sanjay Zalke said...

Great!!! simple approach...
Keep it up... got it work after 2hrs of hair pulling..
Thx

Sanjay

Anonymous said...

great. i wish microsoft would actually use their products. that way they could tell us this stuff from the start

Anonymous said...

Hi Vishal,

I am now working on a web Application and want to include few pre-compiled dlls into my application. I tried copying them into the bin folder but that didn't help. The bin folder also doesn't show in the solution explorer window. Please advise how to include the dlls into my web application (not website).

Thanks & Regards,
Aniruddha Ghoshal.

Vishal R Joshi said...

There is a small button on solution explorer to show the hidden folders and if you do that then the bin folder will show up.

If the pre-compiled DLLs are not same as your web application then just adding reference to those DLL by right clicking your project might be ok.

Some people create a references folder outside of the project in the solution and add the DLLs there and then add references from the project to those DLLs. Then that folder can be checked into source code control.

Hope this helps.

msbyuva said...

Thanks it saved me from a big confusion. Good Article.

Ben Barreth said...

Thanks for this article. We were having issues with a single class in our App_code folder for our WAP and this was the issue.

Anonymous said...

How do you call a class in the App_Code folder if its build action is marked as content?

Anjaneya said...

i am trying to mix VB and C# in the same project...is it possible?please give me a idea how to place mixed classes..

Vishal R Joshi said...

Hi Anjaneya,
VB & C# in same Web Application Project is not possible. You can do that using Web Site Project though.
You can read more about the differences at http://vishaljoshi.blogspot.com/2009/08/web-application-project-vs-web-site.html
Hope this helps.
Vishal

Bhagwat Prasad Sharma said...

Hi Vishal,

i have no source code of my wap bcz i have compiled all code in .dll files, and no backup of source code i have but now i want to edit project.. how can i get my source code(aspx.cs files) pls help me thanx in advance

Bhagwat Prasad Sharma said...

Hi Vishal,
How can i retrieve source code from compiled .dll files pls help me thanx in advance

Vishal R Joshi said...

Hi Bhagwat,
Sorry you are having to deal with this. I do not think there is a easy way to do this using official MSFT tools, you might have to use 3rd party tools. Maybe you start with Reflector and go from there?
Thx
Vishal

Anonymous said...

hello vishal i still don't understand the solution cam you plese tell me in lay man language.

Vishal R Joshi said...

Hi anonymous,
Can you please send me an email at Vishal.joshi@microsoft.com on which part you would like me to help out on and I will be happy to explain it in detail.
Thx
Vishal

Knvn said...

I published the website projects(WSPs) as precompiled and I observed that there is no App_Code in the published folder, instead it contains 'App_Code.dll' inside the bin directory. I guess, all the classes that were placed under App_Code folder is compiled to 'App_Code.dll', is it correct? also, if I create a folder named App_Code on the published place and put some class files on it; does it affects the precompiled website?

Vishal R Joshi said...

Hi Knvn,
That is correct the App_Code dll should contain the classes which were in App_Code.
If you add one more App_Code folder on the server which has precompiled site then it is likely to fail as there cannot be two App_Code assemblies as it will cause runtime confusion.
Hope this helps!
-Vishal

RVmag said...

you can use both projets, web site for debugging, web application for publish parameters with the same sources.

Anonymous said...

Most Helpful!! Fixed an issue with this info.

Divya said...

Hi Vishal

Thats really useful!!!could u plz tell me one more thing?What is difference between website and webApp.How to decide which one to choose???

Vishal R Joshi said...

Divya,
Here is the info you are looking for:
http://vishaljoshi.blogspot.com/2009/08/web-application-project-vs-web-site.html
Thx
Vishal

Ayman Mahmoud said...

Thanks alot Vishal R Joshi

Anonymous said...

thank you
that was helpful.

Anonymous said...

Hello Vishal,
I downloaded a open source code that did not have a solution/project file from codeplex and tried to plug this into a standard solution/web project application.

There is an App_Code folder with sub folders. All the classes are written in C#. All the class files are marked as content for Build Action. I still get the CS0246 for the class in the App_Code.

Much appreciate if you can help.

Thanks,
-Chandrika

Vishal R Joshi said...

Chandrika, can you share the solution, coz it is difficult to speculate what the issues could be.
Thanks
Vishal

Anonymous said...

Hello Vishal,
I have sent you e-mail with (hopefully) the link to the open source code. Hopefully you can help me out here.
Thanks,
-Chandrika

password for shared folder said...

Well done. i wish microsoft would actually use their products. that way they could tell us this stuff from the start.

Dheeraj Palagiri said...

Hi vishal,

I got precompile website. App_code folder is created automatically when ever i run the website, and next request i am getting an error saying"The directory '/App_Code/' is not allowed because the application is precompiled."

I deleted it first request is fine then second request again got same error when i looked into the website folder it created app_code folder again which is always empty. Do you know anything about this?

Nagendra Kumar Mava said...

Hi Vishal,

I am facing APP_WebReference issue while converting WSP to WAP. I jave just copied from WSP to WAP. It is not able to identify the web reference could you please help me on this.

Anonymous said...

Thank you very much for this piece of information!

Ajinkya said...

A very nice article thanks a lot... :)

Anonymous said...

Hi Vijay,

Thanks a lot for your brief description.