[1/4/07 - please note: Web Application Projects is now part of Visual Studio 2005 SP1. Web Deployment Project is still a separate download]

 

Microsoft has just put out Version 1.0 of Web Application Projects which is a much needed add-in for Visual

Studio 2005. This add-in project type addresses a number of issues related to page compilation, project creation and management as well as deployment in ASP.NET 2.0 and Visual Studio 2005 by providing a project model that resembles more closely to VS2003 projects. If you've had any kind of issues with project management, compilation or deployment you should definitely check out this new add-in that brings back an old but proven concept.

 

Web Application Projects come in response to some fairly noisy criticism of the stock project model shipped with Visual Studio 2005. Many developers in the community ran into quirky behavior due to the complex new compilation model. Ironically the new stock compilation model was supposed to make it easy to create and work with Web applications, and while it does make many things easier most of the time, the few things it doesn't do well can be major stumbling blocks.

 

Deployment is also affected by the compilation and project model and many developers ended up downright baffled by the messy deployment output generated by stock projects. The output contains a ton of randomly named files and cannot create a repeatable installation unless doing an in-place install including source files.

 

In addition, there are project management issues because stock projects aren't real Visual Studio projects and some features that have always been available to projects like Build Actions, XML Documentation and MS Build support, are simply not available.

Microsoft responds quickly

Microsoft took the issues raised quite seriously early on and got down to build a couple of powerful project template add-ins that addressed just about all of the concerns. Unfortunately these tools didn't make it into the shipping product of Visual Studio 2005 and the tools ended up getting released as add-ins that can be downloaded. The initial tool released was Web Deployment Projects (http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/) which addresses the deployment process by combing the jumble of files that the ASP.NET 2.0 compiler (ASPNET_COMPILER.EXE) creates, into a single assembly, along with the ability to create repeatable installs. Shortly thereafter a second tool called Web Application Projects (http://msdn.microsoft.com/asp.net/reference/infrastructure/wap/) was introduced which essentially brings back a full project model similar to VS2003, but with significant enhancements. Both tools were recently put out as V1.0 releases and both will be integrated into future refreshes and updates of Visual Studio starting with SP1 later this year according to Microsoft. Neither of the products works with Visual Web Developer.

Stock ASP.NET 2.0 Projects - The good and the bad

You may be wondering what all the fuss is about. Stock ASP.NET 2.0 projects may work well for you and if they are, there's no reason to switch or add any tools. I would argue no matter what you do deployment (short of in-place installation with source code) can use the help of Web Deployment projects, but Web Application Projects is something that you need to worry about only you've hit some of the snags of stock projects or you simply like the more standard approach that it offers to project management.

 

Stock ASP.NET 2.0 projects are nice in a lot of ways. One of the highlights of the new stock model is the ability to use file based projects which require no configuration to open a project. You simply point Visual Studio at a physical directory and open it up. Right click on a page, View and Browser and the built in Web Server starts up and you're running the Web Application. Look Ma, no hands!

 

Along the same lines is the ability to make changes to the code of a page, save the page and run it in the browser without having to recompile it. I know, I know – No Compilation? Blasphemy! But I have to admit I got quite used to not compiling my stock projects but simply running pages after changes. This scenario is even nicer if you have the debugger attached to your Web application. You can now make changes to your code while the debugger is attached, refresh the page and see the refreshed code in the debugger. No stopping the debugger, no restarting of the app, this can be a huge timesaver.

 

The final improvement in the compilation model comes if you are using CodeBeside pages – the new partial class model eliminates all of the control definition from the source code of your classes and instead generates them at runtime. There's no code clutter of control and event definitions as there was in ASP.NET 1.1 CodeBehind pages in InitializeComponent, and no longer are there issues with Visual Studio mucking up the control definitions or event hooks because that task has been offloaded for ASP.NET at compile time.

 

All of this is easy and makes getting started with ASP.NET 2.0 easier than what you had to go through with ASP.NET 1.1. It's surely the main reason why Microsoft went through the trouble of cooking up a whole new compilation model to make ASP.NET more approachable.

Stock Projects: A few problems

When I first started using 2.0 Web Projects I was pretty excited. Indeed it did seem much easier to work in 2.0. Especially the Edit and Go functionality and the ability to simply open a project seemed nice especially as I was checking out a lot of sample projects at the time. I started with 2.0 early in the beta and like most people who used these early versions of the time I was just trying to understand the many changes by creating small samples and pages. And ASP.NET 2.0 and the stock project model worked awesome for that. I never really got around to a final compilation of my samples for deployment, and most if not all of my work was with single pages that didn’t have external dependencies or complex page class hierarchies. Life seemed good…

 

Fast forward to the final betas. By now I was getting more familiar with ASP.NET 2.0 and decided to port one of my more complex applications to 2.0. First thing I found that the migration didn't go very smooth – the migration tool missed many of the pages that were inherited off custom Page classes or Pages that referenced CodeBehind classes of other pages. At this point some of the difference between the CodeBehind and CodeBeside model became clear and it took quite a bit of time and experimentation to understand just what you can and can no longer do when dealing with Page inheritance. And where you need to put files. Can I leave it in my Web directory or do I have to put it in APP_CODE? Will ASP.NET generate my controls or not?

 

Most of these issues during conversion had to do with ASPX pages that use inherited page classes. I have a number of pages that use a CodeBehind class that serves a number ASPX pages. This is not easily done in 2.0, unless you create your own control definitions at the base class level (ie. a fair amount of manual work) or resort to using FindControl() in the base class. It took a lot of trial and error to figure out exactly what you can and can't do with page inheritance – things that worked just fine and logically in the previous version of ASP.NET. The process is not easy and although I now have a pretty good understanding of how the page model works, I think it's horribly confusing and riddled with inconsitencies and workaround implementation details that developers should not have to deal with. CodeBehindBaseClass anyone?

 

At the time I figured, I'm upgrading and I didn't do things the ASP.NET 2.0 way that I would if I were starting from scratch today. But unfortunately as I went on with development of new projects I ran into these same quirks over and over again. In most cases I was able to work around the issues, but because of the complexity of the model it's a major time drain working around them.  Ever try to create two master pages and inherit one of them from the CodeBehind class of the first? It can be done but it's not very obvious. Need to load a user control dynamically and can't have a @Register tag on the page? Doing simple things like this shouldn't require any special directives or resorting to Reflection or FindControl() semantics to get a proper reference to a type. The model of ASP.NET 1.1 was simple and elegant and inheritance worked the way you expect it to, whereas the 2.0 model seems too clever and full of workaround hacks and directives to force things to work a certain way. If you are doing cross page/control referencing I bet you have run into these issues and wasted a fair amount of time working trying to find the right combination of directives and inheritance to make it work. It shouldn't be this hard!

 

The next real shock was deployment. When I finally got around to deploying to a staging site, I was stunned of the choices that had to be made. Should I precompile? Should I include the ASPX files in the pre-compilation? Should use fixed names or force assemblies to created for each directory? And the deployment tools built into VS.NET 2005 are pretty lame as they don't even give access to all the options available on the ASP.NET compiler. If you want all the choices you have to use the command line compiler and figure out one of the 20 or so compilation combinations you can come up with through the various options. In fact, I got so frustrated with the options I ended up building a front end GUI tool for the ASPNET_COMPILER.EXE (http://www.west-wind.com/tools/aspnetcompiler.asp) which let me experiment a little more easily with the options.

 

It took me a couple days of experimentation and reflection on the concepts to find a model that I could work with and manage my site reasonably efficiently. Reasonably… the process was far from optimal and involved deleting all existing files in the BIN directory (50 files just for the Web app plus the satellite assemblies) then recopying all of those files into the BIN directory. The worst part though, was that the install was not repeatable – every build created a different set of deployment files with unique names in the BIN directory. The only way to manage deployment was to delete all the files and copy them back up even if I had only a single tiny little change.

 

Updating your site in real-time is also a problem because of this model. There are many binary files that need to get updated and while in process the site becomes unstable and results in errors on a live site with the update in progress. ASP.NET 2.0's workaround solution: Use a placeholder file while the update is in progress – Riiiight.

 

I gnashed my teeth and told myself, "I can live with that. After all I don't deploy that often." But after going through these steps with a few minor updates, finding a small bug with the update and then having to go through this process again, let me tell you this process became more than a little annoying and a considerable time sink.

 

Long story short, over time I've gotten very discouraged with stock Web projects for real project work. I still prefer stock projects for samples and simple projects, but for anything critical I've moved on to Web Application Projects.

 

Luckily Microsoft heard these and other serious complaints (no build actions, source control limitations) from other developers and responded with Web Deployment Projects and Web Applications Projects.

Web Deployment Projects

To address the deployment issues Microsoft shipped a pre-release version of the Web Deployment Projects (WDP) add-in almost simultaneously with the release of Visual Studio 2005. Since then Web Deployment Projects has been released as Version 1.0. WDP addresses only compilation issues and it works in combination with stock projects. It can also be used with Web Application Projects to provide for pre-compilation of ASPX pages in those projects (more on this later).

 

WDP gets added to an existing solution that includes a Web project. You add a new Web Deployment project and this new projects manages the publishing of your project to a specific directory in a similar way that the Publish feature does, but provides a number of useful enhancements and features. WDP still uses the same compilation that ASP.NET 2.0 uses natively and then post-processes the output generated by the stock compiler.

 

The key feature of the tool is that it can create a single assembly of the mess of files that stock project creates. It still doesn't create just a single file – there are still .compiled marker files for each page if you chose to precompile the ASPX pages as well.

 

But unlike stock projects all the files generated use ffxed hash values for file names, so the installs generated are fully repeatable. For example, if you compile to a single assembly the single assembly will be the same name, and each of the .compiled files for the ASPX pages will have the same name as the previous build.

 

This means, now when you deploy, you can in most cases update the single assembly and leave the other files alone. You'd only need to update the .compiled files if you add new files to the project. So if there should a be minor fix after a deploy to the live site, you can now update a single file.

 

A single assembly also means that you are updating a single binary file on the server, which is makes it possible again to do an in place update of the application without shutting down the server and without seeing error messages while the assembly is being updated. No more out of sync assemblies on the server in many cases.

 

Because WDP is a real Visual Studio project it is a straight MSBUILD file and can be triggered for automated builds which was one additional complaint with stock projects. There are also a number of useful features in WDP which allow you replace sections in Web.Config with content from external files. This lets you change your config settings for deployment which are almost surely going to be different from what they are in your development environment. You can also assign version information to the assembly created  - previously the best you could do is store a AssemblyInfo.cs file into your APP_CODE folder which would give a version to the generated APP_CODE assembly only.

 

If you plan on using stock projects with ASP.NET and you plan to deploy a pre-compiled Web site, I highly recommend you combine it with Web Deployment projects to create workable installs.

Web Application Projects

To address the main logistical issues with stock projects mentioned above, Microsoft has provided Web Application Projects (WAP). WAP basically takes us back to the compilation model that Visual Studio 2003 used with some important enhancements and full support of all the ASP.NET 2.0 features. WAP brings back the CodeBehind compilation model, where all CodeBehind code gets compiled by Visual Studio into a single assembly in the BIN directory. When you build your projects you get a fully compiled, single assembly and an in-place installation that is fully self-contained.

 

WAP is provided as a Visual Studio Project project template. To create a new project you Create a new Web Application Project which creates a familiar .csproj or .vbproj file. Unlike VS2003 though, the new project doesn't use FrontPage extensions, but rather accesses the files directly from disk, so it's much faster. The project is a full Visual Studio style project with all the features you'd expect from a project like XmlComments, versioning, compiler switches, build actions etc. As any VS.NET project it's also an MSBUILD script so you can customize as needed with all the functionality MSBUILD allows.

 

If you already have a stock ASP.NET 2.0 project you can use the 'Convert to Web Application' option to automatically convert the project for you. The converter runs through your project and fixes up each of the ASPX/ASCX/MASTER pages updates the CodeFile tags to CodeBehind and adds the new .designer file with the control definitions. I ran into a few issues with control assemblies in the BIN directory not being found. It might be a very good idea to compile your existing project under stock projects just before doing a conversion to ensure all the required dependencies exist in the BIN directory.

 

WAP works like VS2003 projects in that it uses the project file to manage the files that it can see, so rather than simply looking on disk and blindly pulling everything in the directory into the project, WAP only holds what you add to the project. So any files you want in the project, need to be added even if they exist on disk. You can also exclude files to remove them – another feature you couldn't do with stock projects.

 

The key WAP feature in regards to compilation is that it moves the step of control code generation of the ASP.NET page process back into the designer – WAP controls and pages are made up of three files that make up each ASPX/ASCX/MASTER page (C# files shown here):

 

  • The aspx/ascx/master markup file
  • The .aspx.cs file that contains your CodeBehind code
  • The .aspx.cs.designer file that contains the Control definition

 

If you've worked with WinForms 2.0, you're already familiar with this model where your code goes into one file (the plain .cs file) and the designer generated code goes in the other (.cs.designer). The generated code consists merely of the control definitions for the page which gives the base class the proper signature. This is an important shift because with this mechanism the class name is known at original compile time and the class is available in the current, single  assembly of all CodeBehind code, so Page and Control classes can be easily referenced across the application.

 

Visual Studio now compiles these two classes together into the base class. The result of this is that the code generation for the control definitions is no longer delayed until runtime and ASP.NET doesn't need to generate a unique classname for the base class. In fact this class compiles into a single assembly for all CodeBehind classes. Any page class can access any page or control or master class by its CodeBehind type as you'd expect because the type now exists at initial compile time.

 

This simple change solves the problem of cross page referencing of controls and pages, the various inheritance related quirks, and it also makes for a much more speedy compilation process. Compiles of a moderately project with 50+ pages takes about one second with WAP vs. 20-25 seconds with stock projects. If you compile a stock project the process is excruciatingly slow, because ASP.NET actually compiles the entire project including the ASPX files and copies it out to a deployment folder. With WAP a compile only compiles the CodeBehind code – there's no ASPX parsing and the compilation is inplace and results in a single assembly that is placed in the BIN directory.

 

Web Application Projects also supports Edit and Continue, which was a feature squeezed in at the very last minute. Edit and Continue gives you some semblance of the Debug and Go functionality of stock projects. Truthfully though, I'm not a big fan of Edit and Continue; the fact that all but the active source file are locked and inaccessible for editing really is more hassle to me than it's worth. But if you're already using Edit and Continue in WinForms or library projects, you can expect similar behavior with Web applications now. Again, consistency is a virtue.

Web Application Projects and Web Deployment Projects in Combination

On the downside, WAP requires compilation of any change made, so you can't simple execute pages after a change. You can get familiar once again Ctrl-Shift-B to build your project. Fortunately the compile is fast.

 

You can no longer get error detection inside of ASPX pages with WAP alone as the compiler only compiles your CodeBehind classes and not the markup code, so errors there don't show up in the Error display. However, if you still want this useful feature, you can use WAP in combination with Web Deployment Projects and precompile your markup pages.  WDP compiles the markup pages and can also flag the errors in its compilation error display. This compile is slower like stock projects, but it's a great tool to run at least from time to time and ensure that your expression markup is valid in markup pages.

Web Application Projects are for me

I've spent a fair amount of time now both with stock projects and Web Application Projects and I can tell you that I feel much more comfortable and productive with WAP, than with stock projects. Everything just works as you would expect and I've not run into any issues of things that don't work. It's a predictable and proven model that is based on standard .NET principles that anyone who can look at the output generated can understand easily.

 

If you are building reasonably complex projects I think you too will find that this model is a better fit for the way most developers work, even though the model is more rigid. Most importantly it's consistent with the rest of Visual Studio, and not an oddball project type and an oddball compilation model with many intricate clever tricks to make it work.

 

There are doubtlessly some of you who are happy with stock projects too, and if they are working for you, and, unlike me, you are not running into the boundary cases I mention above, by all means stick with stock projects. They are less rigid to work with and the projects are more portable. If I build any sort of demo application or samples, it surely will be done using stock projects.

 

The good news is that should you run into a problem with stock projects that you can't solve you can now easily switch to WAP if necessary. The conversion isn't completely automatic, but it can be done fairly quickly. Even with some of the compiler issues I had in my conversion I ended up doing the 50+page project in about an hour.

 

It is also possible to go back to stock projects although this is a manual process (you can find out more here: http://west-wind.com/weblog/posts/5571.aspx) although I suspect there will be little need to go this direction.

Community Driven

Finally I think that Microsoft did a bang up job getting these tools out to solve the problems with stock projects as they became apparent. Both of WAP and WDP were very publicly discussed and Microsoft listened very carefully to community input during the development cycle. Many features were added after the intial releases came out and public community input was made available. Each new release during the preview cycle brought out many of these new changes very quickly. It's good to see this kind of flexibility at Microsoft after dealing with the slow as molasses monster releases of Visual Studio .NET during the betas.

 

It would have been even better if these tools had made it in the box, but given the timeframe of release that wasn't possible. As it stands these tools will become part of Visual Studio 2005 SP1 later this year and future releases.

 

Note though that neither of these tools work with Visual Web Developer currently, and I don't believe there are any plans to integrate them into updates in the future either. VWD developers will be stuck with stock projects which is probably OK given the scope of VWD.