web.config transform at deploy time not build - asp.net

I'm wanting to know how to perform the following
Build & package an ASP.NET website to the file system
Be able to deploy the website to one or more environments. I want to the transforms of config file to happen at the point of deployment, rather than at the point of building. This way my code is not recompiled for each deployment and there is not risk of new changes being introduced.
From my own reading I'm unsure of how to do this. WebDeploy seems to package, transform and deploy based on a configuration but Im unsure how these steps can be decoupled to avoid the need to recompile code from source control.
Does anyone have any experience in solving this issue?

You can use the Parameterization feature of web deploy a.k.a MSDeploy. You will need to use a parameters.xml file and a setParameters.xml file to dynamically swap out settings since you are not transforming your package at build time.
At deployment time you can pass in any .xml file to set the parameters you have specified in the parameters.xml file. Since the parameters.xml is at the root of your project solution (e.g see example link of where to place the file) then at build time it gets baked into your web package. However, you now have the flexibility to change those values by passing in the setParms .xml file from the command line during deployment. This is different than transforming the values during build time based on configuration settings.
Here is a msdeploy command line example of passing in a ParamFile for a staging environment.
msdeploy -verb:sync -source:package="c:\packages\mypackage.zip" -dest:auto,computername=StagingServer1 -setParamFile="c:\StagingParameters.xml"
See the below links for examples and MSDN technical information:
Web Deploy Parameterization in Action
Parameterization vs. Web.Config Transformation
Web Deploy Operation Settings
Similar question on stackoverflow that provides several methods

Related

Use default values from web.config when using web deploy parameters

I am trying to improve the development and deployment experience in our company by trying to limit the overhead in using multiple environments. We currently have 3 environments: Debug, Test, Release. This means I have multiple configuration files: web.Debug.config, web.Test.config, web.Release.config.
We are using NuGet packages to deploy the internally developed libraries. The library itself is responsible for the configuration values it uses. This is easily done with NuGet transformation files. Thus, when adding a package to a project, the correct environment transformation file is applied to the correct .config file. Using SlowCheetah and some manual modifications to the csproj file, this works quite well. When switching the build configuration during development, the correct .config file is used; when creating a deployment package it also uses the correct .config file.
The problem arises when I want to use a parameters.xml file to allow the release manager to change the configuration values when deploying. (How to: Use Web Deploy Parameters in a Web Deployment Package) He sometimes wants to set up a separate environment to do be able to test certain things, whilst not disturbing the existing test environment.
In theory, the use of a parameters file is the perfect solution. In reality it seems the parameters file is not capable of using the configuration values from the corresponding configuration file when no values are passed. This means that, when we provide a parameters file, we must define the actual default values for each possible replacement value. And of course, this complicates things as their is only one parameters file for all configurations. Always specifying every configuration value when deploying is also not preferred, because this means that, when a configuration value changes, we must change it in two places: the NuGet package and the deployment script which deploys to the default environments.
What would be the easiest way to solve our problem? How can we tell the web deploy wizard to use the default values from the .config file generated when creating the deployment package if no value is filled in?
I have been struggling with this issue as well, The best solution I can come up with is to add parameters via the .pubxml files for each deployment, this means a duplication of efforts unfortunately(Surely someone has a better approach?)

MSBuild: Web application, build once package and deploy many

I'm sure this question has come up before, but I can't seem to find an elegant solution.
I have a web application project with multiple configurations based on deployment environment (Test, QA, Production) along with web.config transforms for each environment. We are using a web deployment package to automatically create the .zip of the app which can be deployed via MSDeploy. It's easy enough to call the package target multiple times, each with a different configuration:
msbuild MyProject.csproj /t:Package /p:Configuration=QA
msbuild MyProject.csproj /t:Package /p:Configuration=Test
But this triggers a complete rebuild of the web project each time before packaging. I want to build once, then apply the web.config transforms, and create separate packages for each environment. Is there an easy way to accomplish this without forcing a complete rebuild for each environment?
Dupe of Build once and deploy to multiple environments with msdeploy & Visual Studio 2012
I've also been wanting a solution to this, but apparently there isn't any real COMPLETE MS solution that I know of. Visual Studio provides the following (as noted here):
Web.Config transformation
Parameterization
Vishal Joshi concluded with the following:
If you can know your environment settings during build time use
Web.Config transformation.
If you would want to create deployment package only once and then
enter the settings during install time then use Parameters.xml
What I would like to see, though, is have the best of both worlds. I want to "package" up a target having ALL the configuration transformations embedded. Therefore, when the IT guy runs the WebDeploy cmd file (that gets generated when you "package"), they can provide a switch of which environment configuration they want (i.e. Dev, Test, Stage, Prod, Release, etc). I don't believe there is a solution from MS out there that does that. :(

any way to pass -Usechecksum to msdeploy using msbuild

I have a website with lots of files using team build and deploying though web deploy packages. The problem i am having is that the packages are build from one of the machines from the farm and the time stamp will not always match. By default with web deploy that means a full site roll and with so many file and the sync across the cluster this is not optimal.
With cmd line deploy i can pass -UseCheckSum and this is solved for manual deployment. Now i'm trying to use a CI build with auto deploy and passing MSbuild arguments though my build setup. Is there a way to get this to deploy in the same manner?
You can't do it in your MSBuild, but you can edit the Microsoft.Web.Publishing.targets file on the build server to apply -UseChecksum.
See my answer here: https://stackoverflow.com/a/13863041/8037
UPDATE: MS has added the ability to pass the UseChecksum flag to VS 2013. To do this, add the following property to the .pubxml file:
<MSDeployUseChecksum>true</MSDeployUseChecksum>
Further information can be found here: http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
If, by "MSBuild" you mean the Web Publishing Pipeline, then the answer is no. The MSDeploy msbuild task supports a UseChecksum property, but the WPP targets provide no mechanism through which you can set it. This is also true of a number of other features (like stored credentials).

MSBuild - Perform all config transforms at once - and transform other files

I have been working on a build script for a website that we have. The website is a classic asp web app with an asp.net website in a folder of the classic asp web app.
We have different versions of the global.asa that need to be substituted instead of different web configs. We are in the process of moving to a continuous integration environment so much of this still new to me. I've written a build script that performs the following tasks.
Cleans the buildartifacts directory if it exists.
Builds the solution file with whatever configuration is passed in. This produces output with each project in a separate folder.
Copies the files into the required folder structure.
Packages up the result using MSDeploy as sync.
My first problem is this ...
When I run the MSBuild task like so ...
<MSBuild Projects="$(SolutionFileName)"
Properties="Configuration=$(Configuration);OutDir=%(BuildArtifacts.FullPath)" />
It builds the web app but does not apply any transformations. I would have assumed that MSBuild would apply the transforms automatically. Instead I end up with all 3 config files in the output folder that contains the build. Why is this? I've done some searching here, and here and they are using a separate task to perform the transformation. IF Visual Studio can apply the transforms and Visual Studio uses MSBuild I would think that MSBuild could apply transfromations? Isn't MSBuild configuration aware? Also if I have to do it separately, can I perform all transformations at once, if there are multiple config files in multiple folders at each level of the folder structure.
My second problem is ... being a classic asp web app we can't really use config files for this part of it because ... well I'm not sure how the classic asp web app would access the config file? So we have different versions of the global.asa file that would normally get replaced manually. I suppose I could do some sort of search / copy the specific asa files that we require at that time, but is there a way to perhaps use transformations to do this task?
Maybe this is not exactly what you need. I'm using XmlPreprocess tool for config files manipulation. I'm using one mapping file for multiple environments. You can edit mapping file by Excel. It is very easy to use.
You can call it from MSBuild script using Exec task.
Regarding the issue of transformations ... once we sorted out deployment with msdeploy we found out that msdeploy will actually perform the transformations on deployment. It stores the transformation data in one of the xml files that get created with the package.

Can't msdeploy web package to temporary folder?

We've got an Asp.Net web application we're trying to get pseudo-deployed to a folder, and I'm starting to think Microsoft are crazy -- why is it so hard to get a WAP to do a "Local FileSystem" deploy as part of MSBuild?
I can build with this:
msbuild .\SubSite.csproj "/p:Platform=AnyCPU;Configuration=Release" /t:Package
And get a nice package.zip which I can deploy to a website...
However, I have two projects in my solution, which I need to combine before I ship them, so I want to deploy both packages into a folder, and then re-package that folder. Despite the documentation on technet to the contrary, it doesn't seem to be possible to do:
msdeploy -verb:sync -source:package=.\SubSite.zip -dest:contentPath=.\Www\SubSite
Because you get the error:
Source (sitemanifest) and destination (contentPath) are not compatible for the given operation.
Does anyone have a suggestion of how I could web deploy two sites inside one another without manually copying files out of a "PackageTmp" folder? I mean, I'm aware that I could just skip zipping the package and manually copy the files out to do this, but I'm not happy about having to create a custom target, and there's no other way to find that just to do something that should be built in.
We did eventually figure out how to do this, but I'm not really happy about it ;-)
Basically, (as mentioned elsewhere on so), you can call msbuild with the target set to _WPPCopyWebApplication. You can also specify/override the WebProjectOutputDir property when you do that. Something like this (where ${name} are variables we're using)
msbuild ${SourcePath}\Www\UI\UI.csproj "/p:Platform=AnyCPU;Configuration=Release;WebProjectOutputDir=${OutputPath}\AppRoot" "/t:_WPPCopyWebApplication"
msbuild ${SourcePath}\Www\Mobile\Mobile.csproj "/p:Platform=AnyCPU;Configuration=Release;WebProjectOutputDir=${OutputPath}\AppRoot\Mobile" "/t:_WPPCopyWebApplication"
msbuild ${SourcePath}\Www\Service\WebService.csproj "/p:Platform=AnyCPU;Configuration=Release;WebProjectOutputDir=${OutputPath}\AppRoot\WebServices" "/t:_WPPCopyWebApplication"
We can then package up the whole "AppRoot" in a separate step.

Resources