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