Change your development web.config which looks like this:
<?xml version="1.0"?> <configuration> <connectionStrings> <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings> <system.web> <compilation debug="true" targetFramework="4.0">
by adding a Web.DeployTest.config file which looks like this:
<?xml version="1.0"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <connectionStrings> <add name="ApplicationServices" connectionString="Data Source=StaticVoidSqlServer;Initial Catalog=Northwind;Integrated Security=SSPI;" providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> </connectionStrings> </configuration>
Only by default it's tied up with the build configurations (Debug, Release etc) and the Web deploy story.
But I don't want a web deployment package. I want:
- a normal "Release" configuration build
- a directory containing all the website files that I can XCopy deploy (like old school Visual Studio 2008 publish)
- the web.config transformed with my custom "DeployTest" name.
But that's my requirements. So I wrote an MSBuild file.
Batch file (build.bat)
First here's a standard batch file, "build.bat", to launch it (I want MSBuild 4.0):%systemroot%\Microsoft.Net\Framework\v4.0.30319\MSBuild.exe build.proj /t:Release & pause
MSBuild script (build.proj)
<?xml version="1.0" encoding="utf-8" ?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Release"> <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" /> <PropertyGroup> <!-- properties that are used in this build file - referenced as $(PropertyName) --> <ProjectName>StaticVoid</ProjectName> <DeployConfiguration>DeployTest</DeployConfiguration> <PublishPath>$(MSBuildProjectDirectory)\..\Publish\</PublishPath> <OutputPath>$(PublishPath)\StaticVoid\</OutputPath> <PackagePath>$(PublishPath)\StaticVoidPackage\</PackagePath> <TransformInputFile>..\StaticVoid\Web.config</TransformInputFile> <TransformFile>..\StaticVoid\Web.$(DeployConfiguration).config</TransformFile> <TransformOutputFile>$(OutputPath)\Web.config</TransformOutputFile> <ImageResourcesPath>..\ImageResources</ImageResourcesPath> </PropertyGroup> <ItemGroup> <ImageResources Include="$(ImageResourcesPath)\*.jpg" /> </ItemGroup> <!-- targets --> <Target Name="PublishWebsite"> <Message Text="Publishing Website" /> <RemoveDir Directories="$(PublishPath)"/> <!-- do a deploy --> <MSBuild Projects="..\StaticVoid\StaticVoid.csproj" Properties="Configuration=Release;OutputPath=$(PackagePath);DeployOnBuild=true;DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;AutoParameterizationWebConfigConnectionStrings=false;_PackageTempDir=$(OutputPath)"/> </Target> <Target Name="Transform"> <!-- transform the web.config --> <TransformXml Source="$(TransformInputFile)" Transform="$(TransformFile)" Destination="$(TransformOutputFile)" /> </Target> <Target Name="BuildWebsite" DependsOnTargets="PublishWebsite"> <!-- we don't need the deployment package, we wanted the published files to copy manually --> <RemoveDir Directories="$(PackagePath)"/> <!-- copy the unmanaged resources --> <Copy SourceFiles="@(ImageResources)" DestinationFolder="$(PublishPath)images" SkipUnchangedFiles="true" /> </Target> <Target Name="Release" DependsOnTargets="BuildWebsite; Transform;"> </Target> </Project>
A little explanation
The MSBuild task for the website project (StaticVoid.csproj) has a whole set of extra properties set which make it do a deploy.The regular deployment package is written to $(PackagePath). I don't care about that, so I delete it.
(Broken here to be easier to read:)
<MSBuild Projects="..\StaticVoid\StaticVoid.csproj" Properties="Configuration=Release;
OutputPath=$(PackagePath);
DeployOnBuild=true;
DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;
AutoParameterizationWebConfigConnectionStrings=false;
_PackageTempDir=$(OutputPath)"/>
The actual directory and files that I wanted are written to $(OutputPath) using the _PackageTempDir property.
For the transform, note the msbuild xml must have Project ToolsVersion="4.0" and
<UsingTask TaskName="TransformXml"with $(TransformFile) defined as
AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
And then the transformation:
<TransformXml Source="$(TransformInputFile)" Transform="$(TransformFile)" Destination="$(TransformOutputFile)" />
<TransformFile>..\StaticVoid\Web.$(DeployConfiguration).config</TransformFile>Simply changing the DeployConfiguration property lets me have test and production builds which transform things nicely.
Update: the old _CopyWebApplication still works too
In Visual Studio 2008 you could use this task:<MSBuild Projects="..\StaticVoid\StaticVoid.csproj" Targets="ResolveReferences;_CopyWebApplication" Properties="Configuration=Release; WebProjectOutputDir=$(OutputPath); OutDir=$(OutputPath)\bin\" />This still works in Visual Studio 2010's MSBuild (and you don't have a package directory to delete).
The transforms can still be done manually.