.NET Website and Web Applications

March 03, 2011

When it comes to working with .NET on the web you have a lot of flexibility on how you approach a project. One particular aspect which seems to be a constant point of contention is the differences between Visual Studio's Website (WS) and Visual Studio's Web Application project (WAP). I had to work with both and over a long time and lot of arguments I learned quite a bit about the differences. Almost anyone who has written an article about this will tell you that you can accomplish pretty much any task with either approach and that choosing one over the other really comes down to your preference and situation. I started working on the WS model and have found that it is suitable for some tasks but the longer I develop the more I find myself using the WAP model because the environment and tools it offers tends to help me accomplish my goals faster and with more precision. It should also be noted that both project types are still reliant on IIS and the model type you choose really only changes the way you work with the project, not how IIS views the files. It's more a difference in the paradigm the two offer. 

Before we start detailing the differences between the two let's discuss the the similarities. There are a number of features inherent in .NET that both the WAP model and the WS model support. For those not familiar with binary library files, both project types support a bin folder where you would place the *.dll files resulting from the compilation of either your libraries or 3rd party libraries. The most important and possibly the least understood aspect is the runtime compilation model. MasterPages, Pages and UserControls can reference class files. They have the option of either referencing a "CodeBehind" (compiled class) or a "CodeFile" (an uncompiled class). Either project type will compile a CodeFile at runtime. This is important because a WAP is mistakenly thought to not support runtime compilation which leads to the notion you cannot make changes to the code without a rebuild. This is most likely because when you create a MasterPage, Page or UserControl in a WAP it defaults to CodeBehind but you can just as easily change it to CodeFile and it'll work. In either model file structure is really up to you to define. There are some system folder types (App_Data, App_Browsers) that you can setup and use but other than those, how you create your model is up to you. Both project models will also support Web Services and LINQ and again this is because IIS and .NET support them not because the model you chose does.

Diving deeper into the details of a WS model, it's a more on-the-fly approach. Any classes in your App_Code folder or referenced by the CodeFile attribute are compiled on the fly when they're updated. For those of you who are coming from a PHP background or aren't familiar with creating compiled class libraries will find this model to be more natural. If you get to a point where you want to manage a Class Library project you'll first want to create a solution file to keep things organized. Although the classes in your App_Code folder will automatically be added to your intellisense to get the intellisense working for 3rd party libraries or your own Class Libraries you will have to manually add references to the bin files in your web.config. If you do work with Class Libraries in this way, when you build them you will also have to manually move the bin files into your website's bin folder. Also to note, since I have built a lot of Sitecore applications and you may also fall into that category, Sitecore references a lot of bin files in the system for custom server controls or custom fields and you will have a very difficult time referencing those classes in your App_Code folder this way. If you're working with Sitecore you may also want to read up on the SDN discussion about it. One of the features people often tout is the fact that you can work directly on a server to fix or asses issues. You may also want to work on a website from your remote machine using FrontPage Extensions or you may not be working on a production server at all. Maybe you're just working on a remote development instance or you also may not be working with anyone else who might conflict with your particular coding style. Who knows. Personally I find that working on the server is overrated and usually dangerous. If you're worried about being able to diagnose bad code on your server I would suggest changing how you deploy code and consider relying on SVN for management so you can rollback to stable versions. You could also test your environment locally before you deploy as a means of mitigating risk on the server end. It seems like a lot of overhead at first but when the server crashes and you break out in a cold sweat you'll realize that more planning on the front end isn't such a bad idea. Mark Ursino, a good friend, also mentioned "in WSP's App_Code, the more classes you have the more likely your Visual Studio will freeze when you save a class b/c it needs to build it all on the fly. in a WAP theres no lag bc it builds when you hit build."

The WAP model is a project based model that has structure inherently in it. You will have a solution file that will encompass the entire project. You will at least have a Web Application Project. In most cases you'll also have a supporting Class Library Project(s). When you want to reference a Class Library, all you need to do is right-click on the references section and choose from projects, bin files or .NET classes. These references aren't used for deployment but only for compilation and intellisense which you'll be loving the ease in which you can get working. These references also copy over the the bin files to your local bin folder automatically when the project is built. You should note that you're only required to rebuild the library you've changed and not everything in the solution. Also any references to libraries will cause dependent libraries to be rebuilt as well. Aside from the technical aspects, rebuilding a library is a point where many developers splinter. This is because  some view the build process as a hassle. When you update class files that are not CodeFiles in a WAP model you will have to rebuild the project that contains them. At first, initially I worked with the WS model, it annoyed me because I was use to just going to a browser and hitting refresh and debugging through the browser. This was just simply how I was use to working and it seemed simple and fast. To me the overhead associated with building the project to test changes was daunting, but over time when I looked closer at the approach I found advantages to building the project before running it. The most obvious is that although it seems faster to not have to compile a project frequently, the time you'll spend debugging through your browser will likely take you longer. This is because when you build your project you'll recieve a list of specific errors and locations in your code. This allows you to pinpoint the issues and solve them before you even hit refresh. You'll still be faced with flushing out runtime errors but that's a disconnect between your data and your modeling. As you're library grows or the number of libraries grow, you'll find that the compilation model is well suited to helping you keep things running smoothly when you need to do complex tasks like large scale namespace changes or method signature changes. And believe me, when your build catches some obscure reference to a method signature that you've changed, you'll be thanking the good folks at MS for providing the tools that prevented you from bringing your site to it's knees. You'll also find greater flexibility with this model in that you can continue to work with pages on a runtime compilation model, but the code will still be checked when you run a build giving you compile time support on runtime code. Also if for any reason your page doesn't compile you can simply right-click and exclude from the project and the build will ignore that page. In comparison another feature of this model is that you're able to run all your pages to run off compiled code. Compiled code's benefits are two-fold. First you're code has a lot of performance gains since it's already machine code and ready to run and second that you can prevent others from modifying or reverse engineering your library through obfuscation techniques should you require it. It's good to have when you're building a product or deploying your code into unknown territory and want to attempt to retain some control over your intellectual property.

Overall I see the differences between the two as the difference between a trial version of software and the pro version. I say this because there are a lot of features in a WS model that can be reproduced in a WAP model but the converse is not true. You can use the WS model out of the box and get things going quickly and deploy and manage it just as quickly. You can also support more complex projects with the WS model as your project grows. I find, and this is only my opinion for what that's worth, when you get to a certain level where you want to have greater structure and control over how things are managed with better tools you're going to be finding that you'll start leaning on the WAP model. You may want to consider that as your Class Library grows you'll be forcing the server to compile it in its entirety at runtime. Also to note is that as you work with teams you'll build more and more complex distributed systems that will likely rely on WAP's tools. A good example of this is when using a Continuous Integration Server. You're going to be running MS build scripts to compile your projects on a development server when code is checked into your Version Control system and you're going to want your team using the WAP model. But don't take my word for it, for your own sake do the research and try both. Determine for yourself what works and what doesn't and don't listen to what anyone else is saying.