Web Deployment Projects to the Rescue
As you can see there are lots of problems and no sensible deployment options with ASP.NET 2.0's stock projects. It's a pain primarily because you can't create a single deployable assembly and you can't create a repeatable install. The best you can hope for is a full re-deploy of your BIN
directory that potentially contains a lot of files.
Even before ASP.NET 2.0 shipped, Microsoft got an earful from developers about the new deployment scenarios and they quickly responded by creating a tool called Web Deployment Projects (WDP)
as an add-in for Visual Studio.
To create a new WDP project you add a WDP project to your Visual Studio .NET solution (see Figure 8).
WDP is a separate MSBuild-compatible project that you can administer through a Project Property Pages interface. WDP's most important feature is that it can create a single assembly from the mess of files that the ASP.NET compiler creates from stock projects. There are actually several other options for compilation including creating directory-level assemblies or page-level assemblies, but WDP adds support for fixed names for each of these options so the compilation of these assemblies is repeatable.
|Web Deployment Projects can create a single assembly out of the mess of files that stock projects create on compilation.|
|Figure 8: Web Deployment Projects are added as a separate project that ties to the Web project in the solution. The tool provides the ability to compile the entire Web site into a single assembly.||
|Figure 9: The key feature of Web Deployment Projects is the ability to create a single assembly from your Web site code.||
When you run WDP you can specify an output path, and how you would like to "merge" your Web project output. WDP takes over the ASP.NET pre-compilation process by first creating a standard ASP.NET compilation of your site and then merging the resulting assembly output into a single assembly, one assembly per directory or one assembly per page. In all cases, it uses repeatable names for the assemblies created. You'll see the main configuration form for WDP in Figure 9
The tool's other options include signing and versioning the resulting assemblies, and the ability to create a virtual directory in the output folder. It even has the facility to change the content of your web.config
file by overriding specified sections with content from an XML file.
Because WDP is a Visual Studio .NET project type, it is also an MSBuild script that you can automate for build automation, which is difficult to do with stock projects. And while you can integrate WDP with Visual Studio as a new project type, the tool also provides a new ASPNET_MERGE.EXE command line utility which you'll find in C:\Program Files\MSBuild\Microsoft\WebDeployment.
You can run this utility against a compiled ASP.NET project and produce the desired assembly merging. I used this tool to provide the integration into the ASP.NET Compiler Tool shown in Figure 7, which is compatible with this tool and can merge into a single assembly as well.
If you use stock projects with Visual Studio 2005, WDP is a no-brainer because it produces much more manageable deployment output. The output generated still includes .compiled files in most cases, but because output is repeatable you don't need to redeploy these files every time. In most update scenarios you only update the main assembly (plus any changed support assemblies).
Web Application Projects
The project, compilation and deployment model in ASP.NET 2.0 gathered criticism from many developers early on for inconsistencies and complexities when dealing with inheritance and dynamic loading scenarios, as well as its complicated deployment options. Add to this the fact that stock projects are housed in a project format that is not like other standard Visual Studio projects and you have a recipe for grumbling developers who are used to a fairly straightforward compilation, project, and deployment model from previous versions of Visual Studio.
Again Microsoft listened and heard the community feedback early on and created yet another tool called Web Application Projects (WAP). WAP brings back a more structured project style in Visual Studio that is in many ways more similar to a Visual Studio 2003 project, but at the same time embraces all the new ASP.NET 2.0 features.
First and foremost, WAP is a new Visual Studio Project type. To create a new WAP project you use the New Project dialog as you do with any other project in the Visual Studio IDE. Any project that you create doesn't automatically pick up files off disk like stock projects, but relies on you to add files explicitly. Because the project is a standard Visual Studio .NET project, it automatically contains built-in support for XML comments, compiler directives, and assembly versioning, as well as MSBuild support, pre- and post-build events etc., and you can automate it with MSBuild. All these things that you take for granted in Visual Studio .NET projects are missing in stock projects.
More important though, WAP does away with the CodeBeside model and instead returns to a modified version of the CodeBehind model that ASP.NET 1.x used with Visual Studio 2003. In this model, Visual Studio is responsible for explicitly compiling all CodeBehind classes, and any other classes defined anywhere in the project. So, all the code in your project compiles into a single assembly.
|Web Application Projects bring back sanity to the Web development process with a predictable and consistent project and compilation model.|
Because WAP brings back a true Visual Studio project, it is stricter than stock projects. You can't mix C# and Visual Basic .NET code in the same WAP project, and you have to explicitly compile your code in Visual Studio each time you make a change to any of the CodeBehind classes. Debugging is also more exactinga code change in most cases requires you to recompile and restart the debugger.
However, compilation is once again fast with WAP. I have one project with roughly 80 pages and control classes and it compiles in a couple of seconds. Using stock projects a full compile of this project took a painful 25-30 seconds. Using WAP you'll have to get used to the Ctrl-Shift-B three finger salute (or F6) for building your projects for every code change you make. But, in my opinion, it's a small price to pay for the simpler model that WAP provides.
WAP also supports Edit and Continue if and only if you use the built-in Web server to debug your applications. The built-in Web server is required because Visual Studio needs to control the parent process it debugs when you use Edit and Continue. This is not possible when you're debugging against IIS, which attaches the debugger to a running instance of a worker process.
The single assembly compilation for all CodeBehind code does away with a lot of the problems regarding inheritance and control and page referencing. Every page and control in the Web project is guaranteed to be able to freely reference every other control and page in the project, because they all end up in the same assembly. The page parse tree classes are still separate, but all the base classes exist in a single assembly that defines both the control properties and custom method interface from your user code. The class interface is no longer split across two classes as is the case in the CodeBeside model, which is the root of many of the problems I discussed earlier. Figure 10 shows the page compilation model.
|Figure 10: Web Application Projects uses designer-generated partial class code to create the page base class for ASP.NET pages and compiles all project code into a single assembly.|
The model is essentially similar to the CodeBehind model in Visual Studio 2003, but WAP projects handle the CodeBehind classes a bit differently than Visual Studio 2003 did. It uses partial classes to separate out the user code and the designer-generated control definitions. So a WAP page consists of three different files:
- Default.aspxthe markup page
- Default.aspx.csthe CodeBehind class of your user code
- Default.aspx.cs.designerthe control property definitions
shows the page and class headers for these three classes.
If you're familiar with Windows Forms 2.0 in Visual Studio, you've seen the .designer partial class approach, which creates a separate partial class that contains control property definitions. By not generating code into the CodeBehind class, WAP keeps the user code file clean like stock projects, and also minimizes problems by keeping the designer file and visual designer surface in sync. This seems like a subtle change but it has a big effect. By creating property definitions on the user code base class, the class interface is fully defined at this level, so when Visual Studio compiles these classes into a single assembly, the classes are fully defined and you can reference them from anywhere in the project as the generated CodeBehind assembly is global to the Web application.
The other big benefit of WAP is that it makes deployment much easier than stock projectseasier even than stock projects with WDP. When you compile a WAP project the BIN directory holds a single assembly. You can now deploy your BIN directory, plus any ASPX/ASCX/MASTER files and any static files.
After deployment, if you find a bug and need to make a quick change you can make the change, recompile the project, and simply upload the CodeBehind assembly back to the server, which is much easier than the stock project's approach of re-deploying and then copying the entire barrage of files to the server.
By itself, WAP does not compile the ASPX/ASCX/MASTER pages of the project, so by default you still have to deploy those files to the Web site and sync them up with your development or staging site. Because WAP doesn't compile markup pages, it also doesn't directly catch errors in these pages. However, you can combine WAP and Web Deployment Projects and let WDP compile the entire site for a binary-only installation as described earlier. You won't end up with as clean an install because WDP will create .compiled files, but it's still a lot cleaner than you would end up with using stock projects.