ASP.NET Web Application: Publish/Package Tokenizing Parameters

ASP.NET Web Application: Publish/Package Tokenizing Parameters

  • Comments 0

 

Today I just saw a question posted on stackoverflow.com asking Why are some Web.config transforms tokenised into SetParameters.xml and others are not? Let me give some background on this topic for those who are not aware of what the question is.

With Visual Studio 2010 when you package your application using the Build Deployment Package context menu option, see image below.

When build the package by default the package will be created in obj\{Configuration}\Package\{ProjectName}.zip where {Configuration} is the current build configuration, and {ProjectName} is the name of the project. So in this case I since I’m building with Debug and the project name is MvcApplication1 the package will be placed at obj\Debug\Package\MvcApplication1.zip. If you take this package and then import into IIS 7 with the “Import Application” option shown below. Note: The machine must have the Web Deployment Tool (aka MSDeploy) installed.

Once you click on Import Application then browse out to the package you will be shown a screen which prompts your for parameters. Its shown below.

 

On this screen you can see that we are prompting for a couple parameter values here. One is an IIS setting, Application Path, and the other is a connection string which will be placed inside the web.config file. If your Web Application Project (WAP)  had 5 different connection strings then they would automatically show up here on this page. Since connection strings are replaced so often we create parameters for all connection strings by default. You can define new parameters on your own, quite easily actually, but that is the topic for another blog post.

Now back to the question. He is asking why do we “tokenize” the connection strings in web.config. To clarify take a look at my web.config file below.

<configuration>

  <appSettings>

    <add key="setting01" value="value01"/>

  </appSettings>

 

  <connectionStrings>

    <add name="ApplicationServices"

         connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"

         providerName="System.Data.SqlClient" />

  </connectionStrings>

 

</configuration>

 After I perform a package this will get changed. Take a look @ the web.config file which resides in the package (you can get to the file at obj\{CofigurationName}\Package\PackageTmp\web.config). You will see what is shown below.

<configuration>

  <appSettings>

    <add key="setting01" value="value01"/>

  </appSettings>

  <connectionStrings>

    <add name="ApplicationServices"

         connectionString="$(ReplacableToken_ApplicationServices-Web.config Connection String_0)"

         providerName="System.Data.SqlClient" />

  </connectionStrings>

 

</configuration>

So his question is why is the connection string replaced with $(ReplacableToken_ApplicationServices-Web.config Connection String_0) and nothing else is? We do this because we do not want you to accidently copy your web to a location and have it executing SQL statements against a SQL server which you did not intend. The idea is that you will create a package that you can deploy to many different environments. So the value that was in your web.config (or web.debug.config/web.release.config if you are using a web.config transformation) will not be placed inside the web.config in the package. Instead those values will be used as defaults in the package itself. We also create a SetParameters.xml file for you so that you can tweak the values. For my app see the MvcApplication1.SetParameters.xml file below.

<?xml version="1.0" encoding="utf-8"?>

<parameters>

  <setParameter name="IIS Web Application Name"

                value="Default Web Site/MvcApplication1_deploy" />

  <setParameter name="ApplicationServices-Web.config Connection String"

                value="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" />

</parameters>

The idea is that you can deploy your package in 2 ways. Through the IIS Manager which will prompt you for the parameters or you can deploy using msdeploy.exe with the –setParamFile switch to specify the path to the SetParameters.xml file. In this case I could create a QA01.SetParameters.xml file along with a QA02.SetParameters.xml file to deploy my web to my two QA servers. How do we do this?

 How connection strings are tokenized

 You might be wondering how the connection strings are tokenized to begin with. With Visual Studio 2010 we released web.config transformations, which all you to write terse web.config transformations inside of files like web.debug.config/web.release.config. When you package/publish your web these transform files are used to transform your web.config based on what you expressed in the appropriate transform file. We have an MSBuild task TransformXml which performs the transformation. We use that same task to tokenize the connection strings. If you are interested in the details take a look at %ProgramFiles32%\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets in the AutoParameterizationWebConfigConnectionStringsCore target.

Now what if you do not want the connection string tokenized?

Prevent tokenizing connection strings

If you want to prevent your web.config connection strings from being tokenized it’s pretty easy. All we need to do is the add a property to the build/package/publish process. We can do that in 2 ways. Edit the project file itself or create a file with the name {ProjectName}.wpp.targets where {ProjectName} is the name of your project. The second approach is easier so I use that. In my case it would be MvcApplication1.wpp.targets. The contents of the file are shown below.

<?xml version="1.0" encoding="utf-8"?>

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

 

  <PropertyGroup>

    <AutoParameterizationWebConfigConnectionStrings>false</AutoParameterizationWebConfigConnectionStrings>

  </PropertyGroup>

 

</Project>

Note: You may need to reload the project in Visual Studio for this to take effect.

Inside of this file I have declared the property, AutoParameterizationWebConfigConnectionStrings, to be false. This is telling the Web Publishing Pipeline (WPP) that it should not replace replace the connection strings with tokens, instead leave them as they are.

Questions/Comments???

Other Resources

 

 

 

Sayed Ibrahim Hashimi - @sayedihashimi 

Leave a Comment
  • Please add 3 and 8 and type the answer here:
  • Post