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