2

I've tried a number of different configurations with this and I haven't achieved my result.

TL;DR

I'm trying to add config transforms into my build process and am looking for the right way to do it from MSBuild so that it shows up in my deployments via MSDeploy.

Background

  • I have an WebApp (MVC3), a Core app (CS Class Lib), and two test class libs, one for each.
  • I have a build script in my solution that uses MSBuild to compile.
  • One of those MSBuild targets deploys to an IIS server using MSDeploy
  • This process is working so far both manually and via CruiseControl.NET

Goal

I would like to add Web.Config transforms to this process. I figured I would do something simple at first, like an app setting called "PEAppsEnvironmentName", which I would make Dev, Test, or Prod based on the current environment.

Theory So Far

To me, it appears that when packaging with MSDeploy, I'm not transforming the config file.

When I run MSBuild with the DeployOnBuild option set to true, it creates another package that has the appropriately transformed config. It just seems like somehow I can't get it all to match up. The end result is that the web page displays "None" (the initial setting) instead of the transformed "Development" string.

I think if I could find out how to use MSDeploy during the packaging phase to transform the MSConfig, I'd be good to go.

Code

My web.config file

<appSettings>
      <add key ="PEAppsEnvironmentName" value="None"/>
      ...  
</appSettings>

My Web.Dev.config file

<appSettings>
    <add key ="PEAppsEnvironmentName" xdt:Transform="Replace" xdt:Locator="Match(key)" value="Development" />
</appSettings>

My MSBuild Targets

Property group showing default config is "Dev"

<PropertyGroup>
    <Configuration Condition="'$(Configuration)' == ''">Dev</Configuration>
</PropertyGroup>

My MSBuild "Compile" Target

   <Target Name="Compile" DependsOnTargets="Init">
        <MSBuild Projects="@(SolutionFile)" Targets="Rebuild" Properties="OutDir=%(BuildArtifacts.FullPath);DeployOnBuild=True"/>
    </Target>

My MSBuild "Package" Target

<Target Name="Package" DependsOnTargets="Compile;Test">
    <PropertyGroup>
        <PackageDir>%(PackageFile.RootDir)%(PackageFile.Directory)</PackageDir>
        <Source>%(WebSite.FullPath)</Source>
        <Destination>%(PackageFile.FullPath)</Destination>
    </PropertyGroup>
    <MakeDir Directories="$(PackageDir)"/>
    <Exec Command='"@(MSDeploy)" -verb:sync -source:iisApp="$(Source)" -dest:package="$(Destination)" '/>
</Target>

My MSBuild "Deploy" Target

(scrubbed for PWs, etc.)

   <Target Name='Deploy' DependsOnTargets='Package'>
        <PropertyGroup>
            <Source>%(PackageFile.FullPath)</Source>
        </PropertyGroup>
        <Exec Command ='"@(MsDeploy)" -verb:sync -source:package="$(Source)" -dest:iisApp=PEApps,computerName=$(WebServerName),username=[User],password=[Password]'/>
    </Target>
SeanKilleen
  • 8,809
  • 17
  • 80
  • 133
  • possible duplicate of [MSBuild Script and VS2010 publish apply Web.config Transform](http://stackoverflow.com/questions/2905151/msbuild-script-and-vs2010-publish-apply-web-config-transform) – Kyle Trauberman Jun 25 '12 at 19:17
  • @KyleTrauberman I viewed that thread and took into account already that the solution isn't want I'm looking for (and I don't think is considered a best practice nowadays). I'm not attempting to edit the project file, nor am I attempting to create an MSBuild task only to transform web.config (unless that's the only way to go). I think it's different in that I'm asking how to do this with either MSBuild or MSDeploy. – SeanKilleen Jun 25 '12 at 19:20
  • Which build configuration are you using? – frennky Jun 25 '12 at 19:24
  • @frennky one I created called "Dev". I have this listed in my MSBuild config as the default (i.e. if nothing is specified at the command line, use it). When using DeployOnBuild=True in my Compile task, it does spit out a directory that contains a correctly modified Web.config. – SeanKilleen Jun 25 '12 at 19:30
  • @KyleTrauberman apologies; it appears the answer is similar, although the question I think was unique in that it assumed that there must be a better method than that question provided. I'll edit my question/answer to reflect this. – SeanKilleen Jun 26 '12 at 15:30

1 Answers1

1

There was a lot to this question, I'm not sure if I'm fully on the same page as you but I'll summarize my impression of what you are asking. You have an existing web project which is in a solution with other projects. You need to be able to package the web project so that you can publish it to multiple destinations.

I have created a NuGet package which can be used for this exact purpose. It's called package-web. When you add it to your web project it will update the packaging process. When you create a package a few additional files will be included in the package, including all the web.config transform files. A .ps1 file will be created next to the package as well. You can use this script to publish the package. It will prompt you for which transform to run and for all the Web Deploy parameters. You can also save the responses to a file and then just pass them to the .ps1 file so that you can perform non-interactive publishes. I created a 5 minute video on it at http://nuget.org/packages/PackageWeb package web: http://sedodream.com/2012/03/14/PackageWebUpdatedAndVideoBelow.aspx. FYI this is not yet working with VS 2012 but I'm working on the fix and should have it updated by the time VS 2012 is released.

If you don't find that useful you can see how I implemented the solution at https://github.com/sayedihashimi/package-web and you should see examples of everything that you need to do to roll your own.

FYI if you need to transform any files besides web.config on package create then you should take a look at my VS extension SlowCheetah. Here is a blog about how to integrate it into a build server.

Sayed Ibrahim Hashimi
  • 43,864
  • 17
  • 144
  • 178