One may quickly build and deploy an ASP.NET web application via
the Publish option in Visual Studio. This option works great for most simple deployment scenarios but it won’t always cut it. Let’s say you need to automate your deployments. Or you have environment-specific configuration settings. Or you need to execute pre/post build operations when you do your builds. If so, you should consider using Web Deployment Projects.
The Web Deployment Project type doesn’t come out-of-the-box with Visual Studio 2008. You’ll need to Download Visual Studio® 2008 Web Deployment Projects – RTW and install if you want to follow along with this tutorial.
I’ve created a shiny new ASP.NET MVC project. Web Deployment Projects work with websites, web applications and MVC projects so feel free to go with any web project type you’d like.
Once your web application is in place, it’s time to add
the Web Deployment project. You can hunt and peck around
the File > New > New Project… dialogue as long as you’d like, but you aren’t going to find what you need. Instead, select
the web project and then choose
the “Add Web Deployment Project…” hiding behind
the Build menu option.
I prefer to name my projects based on
the environment in which I plan to deploy. In this case, I’ll be rolling to
the QA machine.
Don’t expect too much to happen at this point. A seemingly empty project with a funny icon will be added to your solution. That’s it.
I want to take a minute and talk about configuration settings before we continue. Some of
the common settings which might change from environment to environment are appSettings, connectionStrings and mailSettings. Here’s a look at my updated web.config:
<appSettings>
<add key="MvcApplication293.Url" value="http://localhost:50596/" />
</appSettings>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.net>
<mailSettings>
<smtp from="
[email protected]">
<network host="server.com" userName="username" password="password" port="587" defaultCredentials="false"/>
</smtp>
</mailSettings>
</system.net>
I want to update these values prior to deploying to
the QA environment. There are variations to this approach, but I like to maintain environment-specific settings for each of
the web.config sections in
the Config/[Environment] project folders. I’ve provided a screenshot of
the QA environment settings below.
It may be obvious what one should include in each of
the three files. Basically, it is a copy of
the associated web.config section with updated setting values. For example,
the AppSettings.config file may include a reference to
the QA web url,
the DB.config would include
the QA database server and login information and
the StmpSettings.config would include a QA Stmp server and user information.
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="MvcApplication293.Url" value="http://qa.MvcApplicatinon293.com/" />
</appSettings>
AppSettings.config
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
<add name="ApplicationServices"
connectionString="server=QAServer;integrated security=SSPI;database=MvcApplication293"
providerName="System.Data.SqlClient"/>
</connectionStrings>
Db.config
<?xml version="1.0" encoding="utf-8" ?>
<smtp from="
[email protected]">
<network host="qaserver.com" userName="qausername" password="qapassword" port="587" defaultCredentials="false"/>
</smtp>
SmtpSettings.config
I think our web project is ready to deploy. Now, it’s time to concentrate on
the Web Deployment Project itself. Right-click on
the project file and open
the Property Pages.
The first thing to call out is
the Configuration dropdown. I only deploy a project which is built in Release Mode so I only setup
the Web Deployment Project for this mode. (This is when you change
the Configuration selection to “Release.”) I typically keep
the Output Folder default value – .\Release\. When
the application is built, all artifacts will be dropped in
the .\Release\ folder relative to
the Web Deployment Project root.
The final option may be up for some debate. I like to roll out updatable websites so I select
the “Allow this precompiled site to be updatable” option. I really do like to follow standard SDLC processes when I release my software but there are those times when you just have to make a hotfix to production and I like to keep this option open if need be. If you are strongly opposed to this idea, please, by all means, don’t check
the box.
The next tab is boring. I don’t like to deploy a
crazy number of DLLs so I merge all outputs to a single assembly. Again, you may have another option and feel free to change this selection if you so wish.
If you follow my lead, take care when choosing a single assembly name.
The Assembly Name can not be
the same as
the website or any other project in your solution otherwise you’ll receive a circular reference build error. In other words, I can’t name
the assembly MvcApplication293 or my output window would start yelling at me.
Remember when we called out our QA configuration files? Click on
the Deployment tab and you’ll see how where going to use them. Notice
the Web.config file section replacements value. All this does is swap called out web.config sections with
the content of
the Config\QA\* files. You can reduce or extend this list as you deem fit.
Did you see
the “Use external configuration source file” option? You know how you can point any of your web.config sections to an external file via
the configSource attribute? This option allows you to leverage that technique and instead of replacing
the content of
the sections, you will replace
the configSource attribute value instead.
<appSettings configSource="Config\QA\AppSettings.config" />
Go ahead and Apply your changes. I’d like to take a look at
the project file we just updated. Right-click on
the Web Deployment Project and select “Open Project File.”
One of
the first configuration blocks reflects core Release build settings. There are a couple of points I’d like to call out here:
DebugSymbols=false ensures
the compilation debug attribute in your web.config is flipped to false as part of build process. There’s some crumby (more likely old) documentation which implies you need a ToggleDebugCompilation task to make this happen. Nope. Just make sure
the DebugSymbols is set to false.
EnableUpdateable implies a single dll for
the web application rather than a dll for each object and and empty view file. I think updatable applications are cleaner and include
the benefit (or risk based on your perspective) that portions of
the application can be updated directly on
the server. I called this out earlier but I wanted to reiterate.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>false</DebugSymbols>
<OutputPath>.\Release</OutputPath>
<EnableUpdateable>true</EnableUpdateable>
<UseMerge>true</UseMerge>
<SingleAssemblyName>MvcApplication293</SingleAssemblyName>
<DeleteAppCodeCompiledFiles>true</DeleteAppCodeCompiledFiles>
<UseWebConfigReplacement>true</UseWebConfigReplacement>
<ValidateWebConfigReplacement>true</ValidateWebConfigReplacement>
<DeleteAppDataFolder>true</DeleteAppDataFolder>
</PropertyGroup>
The next section is self-explanatory.
The content merely reflects
the replacement value you provided via
the Property Pages.
<ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<WebConfigReplacementFiles Include="Config\QA\AppSettings.config">
<Section>appSettings</Section>
</WebConfigReplacementFiles>
<WebConfigReplacementFiles Include="Config\QA\Db.config">
<Section>connectionStrings</Section>
</WebConfigReplacementFiles>
<WebConfigReplacementFiles Include="Config\QA\SmtpSettings.config">
<Section>system.net/mailSettings/smtp</Section>
</WebConfigReplacementFiles>
</ItemGroup>
You’ll want to extend
the ItemGroup section to include
the files you wish to exclude from
the build.
The sample ExcludeFromBuild nodes exclude all obj, svn, csproj, user, pdb artifacts from
the build. Enough though they files aren’t included in your web project, you’ll need to exclude them or they’ll show up along with required deployment artifacts.
<ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<WebConfigReplacementFiles Include="Config\QA\AppSettings.config">
<Section>appSettings</Section>
</WebConfigReplacementFiles>
<WebConfigReplacementFiles Include="Config\QA\Db.config">
<Section>connectionStrings</Section>
</WebConfigReplacementFiles>
<WebConfigReplacementFiles Include="Config\QA\SmtpSettings.config">
<Section>system.net/mailSettings/smtp</Section>
</WebConfigReplacementFiles>
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\obj\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\.svn\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\.svn\**\*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.csproj" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.user" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\bin\*.pdb" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Notes.txt" />
</ItemGroup>
Pre/post build and Pre/post merge tasks are added to
the final code block. By default, your project file should look like
the following – a completely commented out section.
<!– To modify your build process, add your task inside one of
the targets below and uncomment it. Other similar extension
points exist, see Microsoft.WebDeployment.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="BeforeMerge">
</Target>
<Target Name="AfterMerge">
</Target>
<Target Name="AfterBuild">
</Target>
–>
Update
the section to remove all temporary Config folders and files after
the build.
<!– To modify your build process, add your task inside one of
the targets below and uncomment it. Other similar extension
points exist, see Microsoft.WebDeployment.targets.
<Target Name="BeforeMerge">
</Target>
<Target Name="AfterMerge">
</Target>
<Target Name="BeforeBuild">
</Target>
–>
<Target Name="AfterBuild">
<!– WebConfigReplacement requires
the Config files. Remove after build. –>
<RemoveDir Directories="$(OutputPath)\Config" />
</Target>
That’s it for setup. Save
the project file, flip
the solution to Release Mode and build. If there’s an issue, consult
the Output window for details. If all went well, you will find your deployment artifacts in your Web Deployment Project folder like so.
Both
the code source and published application will be there. Inside
the Release folder you will find your “published files” and you’ll notice
the Config folder is no where to be found. In
the Source folder, all project files are found with
the exception of
the items which were excluded from
the build.
I’ll wrap up this tutorial by calling out a little Web Deployment pet peeve of mine: there doesn’t appear to be a way to add an existing web deployment project to a solution.
The best I can come up with is create a new web deployment project and then copy and paste
the contents of
the existing project file into
the new project file. It’s not a big deal but it bugs me.
Download
the Solution