Precompiling with Web Deploy
Web Deploy is a great tool for deploying ASP.NET projects: it simplifies deployments, can target IIS 6 or 7, is pretty easy to get working on the server and the project side, and is supported by many hosting providers. It works really well when used along with continuous integration. In the first phase, the project is built and a Web Deploy package is made; the command used is (for example) “msbuild [something.sln or something.csproj or something.vbproj] /m /p:Configuration=release /p:DeployOnBuild=True /p:DeployTarget=Package /p:skipJsHint=true”. In the second phase, the Web Deploy package is deployed to servers for testing.
One of the problems I noticed was that a user could browse around the site and hit a compilation error. For instance, if there was a misspelled variable in an ASPX page, the user would get a standard “500” error page.
One of the purposes of continuous integration, and build/testing systems in general, is to avoid such problems. If the code behind fails to compile, the team is notified immediately – but if the ASPX page fails to compile, we have to wait for a user to report the problem. That is not acceptable.
The aspnet_compiler tool is the solution to this problem. If you use ASP.NET MVC, your project’s MSBuild file will contain a target named “MVCBuildViews” that will run aspnet_compiler for you. Enabling the use of this target by setting the “MvcBuildViews” property makes the build take a bit longer, but there are less surprises – to me, the benefit far outweighs the cost.
So the first option is to simply enable “MvcBuildViews.” “MVCBuildViews” writes the precompiled files to the ASP.NET temporary directory (the precompiled output is not included in the Web Deploy package), so they’ll be used only by the system that invoked the target (in my case, the continuous integration server). So for server deployments, you get the benefit of knowing that the pages compiled (solving the original problem), but you don’t get the other major benefit of precompiling – the startup performance boost.
It turns that combining aspnet_compiler and Web Deploy is a bit tricky. I won’t go into the details, other than to say I figured it out and made an MSBuild target file that can be easily included into projects that use Web Deploy.
So, to get Web Deploy working with precompilation:
- Grab Precompile.targets and put it into the directory with your .csproj/.vbproj project file.
- Modify your .csproj or .vbproj file, add <Import Project=”$(MSBuildProjectDirectory)\Precompile.targets” /> towards the end of the file.
- In your project’s configuration, set the “AspNetCompiler” property to “true” for whatever configurations you want (I have it enabled for the “Release” configuration in my case).
- If you also want to invoke aspnet_merge, you need to ensure the system that does the building has Visual Studio or the Windows SDK installed, then in your project’s configuration, set the “AspNetMerge” property to “true” for whatever configurations you want.
aspnet_merge is another interesting tool that merges assemblies. You can read about its benefits on the aspnet_merge MSDN page. I found that it is beneficial to use aspnet_merge almost always – the only problem I had was on one of my very large projects (with dozens of ASPX page and the total web site size being a few hundred megabytes), aspnet_merge took an exorbitantly long time. For example, on our normal project, it takes ~1 minute. On this very large project, it took over an hour.