Set Web Deploy parameter values in MSBuild - msbuild

I use MSBuild to build and deploy a web application.
MSBuild.exe MySite.csproj /p:DeployOnBuild=True /p:WebPublishMethod=MSDeploy /p:MSDeployServiceURL=mysite.example.com
My site connects to a SQL Server database.
<connectionStrings>
<add name="dbconnection"
connectionString ="Data Source=(local);Initial Catalog=MySite;Integrated Security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>
I develop against a local database, but the connection string needs to be changed when the site is deployed to test or production servers.
I have declared a deployment parameter named dbconnection in a file named parameters.xml
<parameter name="dbconnection"
defaultValue="Data Source={server};Initial Catalog={database};Integrated Security=SSPI;"
tags="DBConnectionString">
<parameterEntry type="XmlFile"
scope="\\Web.config$"
match="/configuration/connectionStrings/add[#name='dbconnection']/#connectionString"/>
</parameter>
I could easily create a parameterized web deploy package and deploy it with msdeploy.
msdeploy -verb:sync
-source:package:MySite.zip
-dest:iisApp="Site1/MySite"
-setParam:name=dbconnection,value="Data Source=.\SQLEXPRESS;Initial Catalog=MySiteTest;Integrated Security=SSPI"
However, I'd really like to be able to do everything in MSBuild. What is the MSBuild equivalent of -setParam?

Parameterization is not used when debugging locally. So all you should have to do is set the defaultValue in your parameters.xml file to your desired connection string.
We create a SetParameters file for each environment (DEV, QA, MOCK, PROD) and call MSDeploy after MSBuild creates a WebDeploy package with the appropriate setParam file. I don't believe there is way to use a custom SetParameters file when deploying directly from MSBuild.
Here is a post that further describes parameterization:
http://dotnetcatch.com/2014/09/08/parameterizationpreview-visual-studio-extension/
UPDATE:
Steven and I worked further outside of SO to understand his use cases better. We confirmed again the MSDeployPublish target does not support setting parameter value overrides. To solve his use case I wrote some MSBuild script to provide the functionality he was looking for and wrote a blog post about it -
http://dotnetcatch.com/2016/04/27/setparameters-via-msbuild-commandline/
It basically works by passing a SetParameters file or list of key/value pairs via MSBuild Properties on the MSBuild.exe commandline. The MSBuild script parses that out and overrides the parameters by setting the MsDeployDeclareParameters ItemGroup.
msdeploy.exe ... /p:MSDeployPublishSetParametersFile=SetParameters.Test.xml
msdeploy.exe ... /p:MSDeployPublishSetParameters=testSetting='changed_fromSetParam';IIS Web Application Name='Default Web Site/app13'

Related

How to specify a custom parameters.xml when building a Web Deploy package for ASP.NET Core?

Overview
I am building a deployable web package that can be imported into IIS that automatically prompts for settings needed by my ASP.NET Core application. I already created a package that will deploy just fine, except after deploying, I need to manually find/edit my appsettings.json file.
I know this package can include a parameters.xml file that will automatically prompt and fill in my appsettings.json when importing an app into IIS. I have already made a parameters.xml file, and manually added it to my package after building it; it worked as expected. I'd just like to have msbuild automatically add the parameters.xml file to the package for me.
A separate project of mine (ASP.NET MVC 4) already does this. For that, I simply needed to put my parameters.xml in the same folder as my .csproj. I tried doing the same here, but had no luck.
Repro Steps
I created an ASP.NET Core Web Application
Using .NET Framework on ASP.NET Core 1.1
I then went to publish my website
Selected 'Folder' (just to get a template)
I then edited the profile and changed the WebPublishMethod to Package and added the three lines below it.
<DesktopBuildPackageLocation>bin\$(Configuration)\$(MSBuildProjectName).zip</DesktopBuildPackageLocation>
<PackageAsSingleFile>true</PackageAsSingleFile>
<DeployIisAppPath>External</DeployIisAppPath>
I then published one more time. Now I get a WebDeploy package that I can deploy to IIS.
Great! but...
I'd like to customize the parameters.xml.
For previous projects, I was able to add a parameters.xml file to my project root, and VS/msbuild would automatically add it to my published package. This currently works for a different project using ASP.NET MVC 4.
So, I tried the same thing for this project. First I added a settings.json with a very simple setting:
{
"SettingName": ""
}
Then I added a parameters.xml file that I know works to my project root. (If I manually replace the parameters.xml file in Sample.zip package, it correctly prompts and replaces my setting when deploying)
<parameters>
<parameter name="IIS Web Application Name" value="External" tags="IisApp">
<parameterEntry kind="ProviderPath" scope="IisApp" match="^c:\\users\\joshs\\documents\\visual\ studio\ 2017\\Projects\\Sample\\Sample\\obj\\Release\\net461\\win7-x86\\PubTmp\\Out\\$" />
</parameter>
<parameter name="Setting Name" description="Enter a custom app setting" defaultValue="Default Setting Value">
<parameterEntry kind="TextFile" scope="obj\\Debug\\net461\\win7-x86\\PubTmp\\Out\\appsettings\.json$" match="(?<=\"SettingName\"\s*:\s*\")[^\"]*" />
</parameter>
</parameters>
Again, I right click and Publish once more. This time with the parameters.xml file.
I expect the Sample.zip to contain the parameters.xml that I added to my project root, but it does not. It is the exact same as from my original publish.
Question
During the build process when creating a web deploy package, how do you include custom settings in the parameters.xml?
I have already tried this...
I already looked at https://stackoverflow.com/a/46338042/2494785, but with no luck, though my command differed slightly from the original poster.
PS C:\Users\joshs\Documents\Visual Studio 2017\Projects\Sample> & 'C:\Program Files (x86)\Microsoft Visual Studio\2017\E
nterprise\MSBuild\15.0\Bin\MSBuild.exe' .\Sample.sln /t:Sample /p:DeployOnBuild=true /p:PublishProfile=FolderProfile /p:
ProjectParametersXMLFile="C:\Temp\parameters.xml"
I was able to solve this from peteawood's comment from an issue posted on GitHub.
https://github.com/aspnet/websdk/issues/201#issuecomment-349990389
In ASP.NET Core 2.0+ you can add the following to your .csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
.
.
<Target Name="AddMoreParameters" AfterTargets="_CreateParameterFiles">
<Copy SourceFiles="Parameters.xml" DestinationFiles="$(_MSDeployParametersFilePath)" />
</Target>
</Project>
SourceFiles should point to the location of your parameters.xml file from the perspective of the .csproj file. My parameters.xml is found in the same directory as my project file.
I believe I can just pass parameters via cmd-line as properties for msbuild.
It's not fully what you asked for I understand.
For example, in the following command I'm passing DeployIisAppPath property:
dotnet publish /p:WebPublishMethod=Package /p:DeployIisAppPath=mysite/myapp /p:PublishProfile=rnddev03-core-dev
and in the output folder we'll get xxx.SetParameters.xml file with:
<parameters>
<setParameter name="IIS Web Application Name" value="mysite/myapp" />
</parameters>

How to ignore the connection string parameter in SetParameter.xml

I am using msDeploy (3.0) to deploy my MVC applicaiton. I have a build pipeline that generates build artifacts for msdeploy and my deploy pipeline applies appropriate web.config transforms on the Web.config before deploying it to the production instances. One of the transforms includes changes to connection string. However, looking at the deployed instances, it seems like my web.config transforms are being overriden by the parameters in setParameters.xml in my build artifacts.
Ideal behavior would be that I would be to avoid adding any Connection string to the SetParameter.xml so that all my connection string overrides will be controlled by my deployment pipeline only. How do I achieve that?
Below is a sample of SetParameters.xml file
<parameters>
<setParameter name="IIS Web Application Name" value="Default/Foo"/>
<setParameter name="Foo-Web.config Connection String" value="Server=Foo,1433;Database=Bar;Integrated Security=SSPI;MultiSubnetFailover=True;App=Something;Connection Timeout=25"/>
</parameters>
Ideally it would look something like
<parameters>
<setParameter name="IIS Web Application Name" value="Default/Foo"/>
</parameters>
I have already tried passing a parameters.xml file to the msbuild step that does not contain the connectsion string parameter but that did not work
After bang my head against the wall for several hours, I finally figured out the solution. MsBuild takes in a parameter - p:AutoParameterizationWebConfigConnectionStrings=false that prevents the connection strings from being parameterized. Unfortunately, there is little or no documentation on this parameter.
You can also set this on a per project basis adding
<AutoParameterizationWebConfigConnectionStrings>false</AutoParameterizationWebConfigConnectionStrings>
to the PropertyGroup of your build configuration.

How to configure Application Pool with MSDeploy

I'm currently using MSBuild to create an MSDeploy package by passing in arguments:
/p:DeployOnBuild=true;DeployTarget=Package
I'm using a parameters.xml file (placed at the root of my website). Another SO question I found tries to set up the application pool.
My parameters.xml file:
<parameters>
<parameter name="Application Pool Name" description="Application Pool for this site" tags="" defaultValue="ASP.NET v4.0">
<parameterEntry kind="DeploymentObjectAttribute"
scope="application"
match="/application/#applicationPool" />
</parameter>
...
</parameters>
but it seems that the archive.xml file inside the msdeploy package generated by the msbuild doesn't have an section with an applicationPool element
How can I get the archive.xml to be generated with this section so that I can set the application pool?
The app pool I want to set will exist already, so I'm not concerned with MSDeploy synching or creating app pools here.
Edit:
I have found this question How do I control the AppPool used for deploy through VS & MSDeploy settings which hints at using wpp.targets to generate a custom provider. I'm exploring how to use this approach to modify the archive.xml file
Assuming you have the correct IIS settings on your project and are running as Administrator, you should be able to specify IncludeIisSettings=true to have the settings included in the zip.
If you need the actual AppPool definition included (so it can be created), you should also set IncludeAppPool=true.

MsBuild and MsDeploy problems

When I publish web project by gui(VS2010) (right click in project and choose Publish menu item, publish Method - Web Deploy) - everything works fine.
Problems appear when I am trying to publish via command line: MSBUILD or MsDeploy.
With MSBuild a package is created with no publishing (only creating package):
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSbuild.exe" Project.sln /p:DeployOnBuild=true /p:DeployTraget=MSDeployPublish /p:MSDeployPublishMethod=WMSVC /p:MSDeployServiceUrl=https://[ip]/msdeploy.axd /p:AllowUntrustedCertificate=true /p:DeployIisAppPath=NlbTestSite /p:UserName=M\DeployUser /p:Password=qwerty
With MsDeploy i get an error: ERROR_USER_UNAUTHORIZED
E:\Work\OutDir\MSDeploy\Package.deploy.cmd" /Y /M:"https://[ip]:8172/msdeploy.axd" /U:"M\DeployUser" /P:"qwerty" -allowUntrusted /A:Basic
My goal is to automate the deployment process using one of those methods.
I want to find out how Visual Studio publishes my project (what command with what arguments)?
UPDATE 19.10.2012 14:52
When I add /p:UseMsDeployExe=true, msdeploy.exe is executed, but nothing is copied.
The execution command:
C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe -source:manifest='E:\[Path]\obj\Debug\Package\[Project].SourceManifest.xml' -dest:package='E:\[Path]\[Project]\obj\Debug\Package\[Project].zip',IncludeAcls='False' -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -declareParam:name='IIS Web Application Name',kind='ProviderPath',scope='IisApp',match='^E:\\[Path]\\obj\\Debug\\Package\\PackageTmp$',defaultvalue='[SiteName]',tags='IisApp' -declareParam:name='IIS Web Application Name',kind='ProviderPath',scope='setAcl',match='^E:\\[Path]\\obj\\Debug\\Package\\PackageTmp$' -declareParam:name='Add write permission to App_Data Folder',kind='ProviderPath',scope='setAcl',match='^E:\\[Path]\\obj\\Debug\\Package\\PackageTmp\\App_Data$',description='Add write permission to App_Data folder',defaultvalue='{IIS Web Application Name}/App_Data',tags='Hidden' -declareParam:name='MainModelContainer-Web.config Connection String',kind='XmlFile',scope='E:\\[Path]\\OutDir\\temp\\Web\.config$',match="/configuration/connectionStrings/add[#name='MainModelContainer']/#connectionString",description='MainModelContainer Connection String used in web.config by the application to access the database.',defaultvalue='metadata=[ConnectionString]"',tags='SqlConnectionString' -declareParam:name='SimpleConnection-Web.config Connection String',kind='XmlFile',scope='E:\\[Path]\\OutDir\\temp\\Web\.config$',match="/configuration/connectionStrings/add[#name='SimpleConnection']/#connectionString",description='SimpleConnection Connection String used in web.config by the application to access the database.',defaultvalue='[ConnectionString]',tags='SqlConnectionString' -declareParam:name='ElmahDB-Web.config Connection String',kind='XmlFile',scope='E:\\[Path]\\OutDir\\temp\\Web\.config$',match="/configuration/connectionStrings/add[#name='ElmahDB']/#connectionString",description='ElmahDB Connection String used in web.config by the application to access the database.',defaultvalue='[ConnectionString]',tags='SqlConnectionString' -retryAttempts=2
No parameters, such as ComputerName, User or password are passed.
Any ideas about the cause?
Problem solved.
Got some ideas from http://root-project.org/work/net/automated-web-deployment-with-msbuild-and-msdeploy
I separated msbuild and msdeploy, and executed msdeploy explicitly.
Here is the template:
msdeploy.exe
-source:package=’C:\SomeWebProject\obj\Release\Package\SomeWebProject.zip‘
-dest:auto,ComputerName=’https://TargetServer:8172/MsDeploy.axd?site=TargetWebSite‘,UserName=’Username‘,Password=’Password‘,IncludeAcls=’False’,AuthType=’Basic’
-verb:sync
-disableLink:AppPoolExtension
-disableLink:ContentExtension
-disableLink:CertificateExtension
-allowUntrusted
-retryAttempts=2
-setParam:’IIS Web Application Name’=’TargetWebSite/TargetWebApp‘
But problem with msbuild still remains.
In your pubxml file, declare the following:
<PropertyGroup>
<UseMsDeployExe>true</UseMsDeployExe>
</PropertyGroup>
Now when you deploy, you should see the call to msdeploy.exe in the publih log.
Make note, though, that it will actually be calling msdeploy.exe directly, and not via the generated deploy.cmd file.

Mixing web.config transforms and Parameters.xml, or something to that effect

I've been using web.config transforms for a while now, for deployment on a few of our projects. What I'm now trying to achieve, is to have Web Deploy's 'Import Package' screen to prompt to check & update several of the variables in , adjusted for each environment.
I know I can use Parameters.xml to introduce these editable variables, but I haven't yet found how to have the defaults updated for different environment targets.
Consider the following neat, but non-overlapping example of wanting to have the user edit the 'specialServer' AppSetting, and have it present a different default when compiled for the NewEnv target:
Sample entry in Parameters.xml:
<parameter name="Special server" description="" tags="" defaultValue="server1-dev.domain">
<parameterEntry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='specialServer']/#value" />
</parameter>
Sample transform for Web.NewEnv.config, setting a different value for
<appSettings>
<add key="specialServer"
value="other-server.domain2"
xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>
Sample of the prompt in Web Deploy:
Any suggestions as to how to update the default value for different build targets?
Thanks.
You would have to generate and new parameters definition file and embed it in your WebDeploy package for each environment.
This would give you different deploy packages per environment and would allow you to specify different default values for those parameters. Obviously doing so undermines the point if parameter transforms and you essentially end up baking in your config, but it's the only way to achieve what you want.
I don't recommend the approach but it may fit your needs.
We use a batch script to call msdeploy. It allows for a parm to specify the Parameters.xml file. Then with multiple Parameters.xml files (one per environment), you can just call msdeploy like:
"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -source:package='D:\mysite.zip' -dest:auto,computerName="testcomp1",includeAcls="False" -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:"D:\mysite.test.SetParameters.xml"