Monday, March 23, 2009

Web Deployment: Web.Config Transformation

We have earlier discussed about Web Deployment and Web Packaging quite a bit, today I wanted to dive into web.config transformation. If you would like to check out the other topics please read through the earlier blog posts below:

Usually web applications go through a chain of server deployments before being finally being deployed to production environment. Some of these environments can be Developer box (Debug), QA Server, Staging/Pre-Production, Production (Release). While transitioning between these environments various settings of the web application residing in web.config file change, some of these settings can be items like application settings, connection strings, debug flags, web services end points etc.

VS10’s new web.config transformation model allows you to modify your web.config file in an automated fashion during deployment of your applications to various server environments. To help command line based deployments, Web.Config transformation is implemented as an MSBuild task behind the scene hence you can simply call it even outside of deployment realm.

I will try to go through below steps to explain web.config transformation in detail

  1. Creating a “Staging” Configuration on your developer box

  2. Adding a “Staging” Web.Config Transform file to your project

  3. Writing simple transforms to change developer box connection string settings into “Staging” environment settings

  4. Generating a new transformed web.config file for “Staging” environment from command line

  5. Generating a new transformed web.config file for “Staging” environment from VS UI

  6. Understanding various available web.config Transforms and Locators

  7. Using Web.config transformation toolset for config files in sub-folders within the project

Step 1: Creating a “Staging” Configuration on your developer box

Debug and Release build configurations are available by default within Visual Studio but if you would like to add more build configurations (for various server environments like “Dev”, “QA”, “Staging”, “Production” etc then you can do so by going to the Project menu Build --> Configuration Manager… Learn more about creating build configurations.

Step 2: Adding a “Staging” Web.Config Transform file to your project

One of the goals while designing web.config transformation was to make sure that the original runtime web.config file does not need to be modified to ensure that there would be no performance impacts and also to make sure that the design time syntax is not mixed with runtime syntax. To support this goal the concept of Configuration specific web.config files was introduced.

These web.config files follow a naming convention of web.configuration.config. For example the web.config files for various Visual Studio + Custom configurations will look as below:

web.config transform

Any new Web Application Project (WAP) created in VS10 will by default have Web.Debug.Config and Web.Release.config files added to the project. If you add new configurations (e.g. “Staging”) or if you upgrade pre-VS10 projects to VS10 then you will have to issue a command to VS to generate the Configuration specific Transform files as needed.

To add configuration specific transform file (e.g. Web.Staging.Config) you can right click the original web.config file and click the context menu command “Add Config Transforms” as shown below:

Add Config Transforms

On clicking the “Add Config Transform” command VS10 will detect the configurations that do not have a transform associated with them and will automatically create the missing transform files. It will not overwrite an existing transform file. If you do not want a particular configuration transform file then you can feel free to delete it off.

Note: In case of VB Web Application Projects the web.configuration.config transform files will not be visible till you enable the hidden file views as shown below:

VB.net web.config Transform

The transform files are design time files only and will not be deployed or packaged by VS10. If you are going to xCopy deploy your web application it is advised that you should explicitly leave out these files from deployment just like you do with project (.csproj/.vbproj) or user (.user) files…

Note: These transform files should not be harmful even if deployed as runtime does not use them in any fashion and additionally ASP.NET makes sure that .config files are not browsable in any way.

Step 3: Writing simple transforms to change developer box connection string settings into “Staging” environment settings

Web.Config Transformation Engine is a simple XML Transformation Engine which takes a source file (your project’s original web.config file) and a transform file (e.g. web.staging.config) and produces an output file (web.config ready for staging environment).

The Transform file (e.g. web.staging.config ) needs to have XML Document Transform namespace registered at the root node as shown below:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
</configuration>

Note: The transform web.config file needs to be a well formed XML.

Inside the XML-Document-Transform namespace two new attributes are defined. These attributes are important to understand as they drive the XML Transformation Engine.

Transform – This attribute inside the Web.Staging.config informs the Transformation engine the way to modify web.config file for specific configuration (i.e. staging). Some examples of what Transforms can do are:

  • Replacing a node

  • Inserting a node

  • Delete a node

  • Removing Attributes

  • Setting Attributes

Locator – This attribute inside the web.staging.config helps the Transformation engine to exactly pin-point the web.config node that the transform from web.staging.config should be applied to. Some examples of what Locators can do are:

  • Match on value of a node’s attribute

  • Exact XPath of where to find a node

  • A condition match to find a node

Based on the above basic understanding let us try to transform connection string from original web.config file to match Staging environment’s connection string

Let us examine the original web.config file and identify the items to replace... Original Web Config file’s connection string section looks as below:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <connectionStrings>
    <add name="personalDB"
     connectionString="Server=DevBox; Database=personal; User Id=admin; password=P@ssw0rd" providerName="System.Data.SqlClient" />
    <add name="professionalDB"
     connectionString="Server=DevBox; Database=professional; User Id=admin; password=P@ssw0rd" providerName="System.Data.SqlClient" />
</connectionStrings>
....
....
</configuration>


NOTE: It is not advisable to keep connection string unencrypted in the web.config file, my example is just for demonstration purposes.

Let us assume that we would like to make following changes to web.config file when moving to staging environment

  • For “personalDB” we would like to change the connectionString to reflect Server=StagingBox, UserId=admin, passoword=StagingPersonalPassword”

  • For “professionalDB” we would like to change the connectionString to reflect Server=StagingBox, UserId=professional, passoword=StagingProfessionalPassword”

To make the above change happen we will have to open web.Staging.Config file and write the below piece of code

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
     <connectionStrings>
        <add name="personalDB"
          connectionString="Server=StagingBox; Database=personal; User   

          Id=admin; password=StagingPersonalPassword"
          providerName="System.Data.SqlClient" xdt:Transform="Replace"    

          xdt:Locator="Match(name)" />
        <add name="professionalDB"
         connectionString="Server=StagingBox; Database=professional; User  

         Id=professional; password=StagingProfessionalPassword"
         providerName="System.Data.SqlClient" xdt:Transform="Replace"

         xdt:Locator="Match(name)"/>
      
</connectionStrings>
</configuration>

The above syntax in web.staging.config has Transform and Locator attributes from the xdt namespace. If we analyze the connection string node syntax we can notice that the Transform used here is “Replace” which is instructing the Transformation Engine to Replace the entire node

Further if we notice the Locator used here is “Match” which is informing Transformation engine that among all the “configuration/connectionStrings/add” nodes that are found, pick up the node whose name attribute matches with the name attribute of <add> node in web.Staging.config.

Also if you notice web.Staging.config does not contain anything else but the connectionStrings section (i.e. it does not have <system.web> and various other sections that web.config file usually has, this is because of the fact that the Transformation Engine does not require a complete web.config file in web.staging.config. It does the merging for you thus saving you duplication of all the rest of the sections in web.config file.

Simplest Approach: If you do not mind replicating the entire web.config file in web.staging.config then you can certainly do so by copying the entire web.config content into web.staging.config and change the relevant nodes inside web.staging.config. In such a situation you will just have to put xdt:Transform="Replace" attribute on the topmost node (i.e. configuration) of web.staging.config. You will not need xdt:Locator attribute at all as you are replacing your entire web.config file with web.staging.config without Matching anything.

So far we have seen one Transform (i.e. Replace) and one Locator (i.e. Match), we will see various other Transforms and Locators further in the post but first let us understand how we can produce the Transformed web.config file for the Staging environment after using original web.config and web.staging.config.

Step 4: Generating a new transformed web.config file for “Staging” environment from command line

Open Visual Studio Command prompt by going to Start --> Program Files –> Visual Studio v10.0 –> Visual Studio tools –> Visual Studio 10.0 Command Prompt

Type “MSBuild “Path to Application project file (.csproj/.vbproj) ” /t:TransformWebConfig /p:Configuration=Staging" and hit enter as shown below:

commandline web.config transformation

Once the transformation is successful the web.config for the “Staging” configuration will be stored under obj -->Staging folder under your project root (In solution explorer you can access this folder by first un-hiding the hidden files) :

transformed web.config

  • In the solution explorer click the button to show hidden files
  • Open the Obj folder

  • Navigate to your Active configuration (in our current case it is “Staging”)

  • You can find the transformed web.config there

You can now verify that the new staging web.config file generated has the changed connection string section.

Step 5: Generating a new transformed web.config file for “Staging” environment from VS UI

Right Click on your project and click Package –> Create Package

Create Package

The Create Package step already does web.config transformation as one of its intermediate steps before creating a package and hence you should be able to find the transformed web.config file in the same place as described in Step 4

Step 6: Understanding various available web.config Transforms and Locators

xdt:Locators

The inbuilt xdt:Locators are discussed below.

  • Match - In the provided syntax sample below the Replace transform will occur only when the name Northwind matches in the list of connection strings in the source web.config.Do note that Match Locator can take multiple attributeNames as parameters e.g. Match(name, providerName) ]

<connectionStrings>
     <add name="Northwind" connectionString="connectionString goes    here" providerName="System.Data.SqlClient" xdt:Transform="Replace"          xdt:Locator="Match(name)" />
</connectionStrings>

·         Condition - Condition Locator will create an XPath predicate which will be appended to current element’s XPath. The resultant XPath generated in the below example is “/configuration/connectionStrings/add[@name='Northwind or @providerName=’ System.Data.SqlClient’ ]”

This XPath is then used to search for the correct node in the source web.config file

<connectionStrings>
      <add name="Northwind" connectionString="connectionString goes here"

        providerName="System.Data.SqlClient" xdt:Transform="Replace"

        xdt:Locator="Condition(@name=’Northwind or @providerName=’

        System.Data.SqlClient’)" />
</connectionStrings>

·         XPath- This Locator will support complicated XPath expressions to identify the source web.config nodes. In the syntax example we can see that the XPath provided will allow user to replace system.web section no matter where it is located inside the web.config (i.e. all the system.web sections under any location tag will be removed.)

<location path="c:\MySite\Admin" >
    <system.web xdt:Transform="RemoveAll" xdt:Locator="XPath(//system.web)">
    ...
    </system.web>
</location>

xdt:Transform

  • Replace - Completely replaces the first matching element along with all of its children from the destination web.config (e.g. staging environment’s web.config file). Do note that transforms do not modify your source web.config file.
    <assemblies xdt:Transform="Replace">
        <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    </assemblies>

·         Remove - Removes the first matching element along with all of its children
<assemblies xdt:Transform="Remove"></assemblies>

·         RemoveAll - Removes all the matching elements from the destination’s web.config (e.g. staging environment’s web.config file).

<connectionStrings>
    <add xdt:Transform="RemoveAll"/>
</connectionStrings>

·         Insert - Inserts the element defined in web.staging.config at the bottom of the list of all the siblings in the destination web.config (e.g. staging environment’s web.config file).

<authorization>
     <deny users="*" xdt:Transform="Insert"/>
</authorization>

·         SetAttributes - Takes the value of the specified attributes from the web.staging.config and sets the attributes of the matching element in the destination web.config. This Transform takes a comma separated list of attributes which need to be set. If no attributes are given to SetAttributes transform then it assumes that you would like to Set all the attributes present on the corresponding node in web.staging.config
<compilation batch="false"

xdt:Transform="SetAttributes(batch)">

</compilation>

·         RemoveAttributes - Removes the specified attributes from the destination web.config (i.e. staging environment’s web.config file). The syntax example shows how multiple attributes can be removed.

<compilation
xdt:Transform="RemoveAttributes(debug,batch)">
</compilation>

  • InsertAfter (XPath) - Inserts the element defined in the web.staging.config exactly after the element defined by the specified XPath passed to “InsertAfter()” transform. In the syntax example the element <deny users="Vishal" />will be exactly inserted after the element <allow roles="Admins" /> in the destinationXML.

<authorization>
     <deny users="Vishal" xdt:Transform="InsertAfter(/configuration/system.web/authorization/allow[@roles='Admins'])” />

</authorization>

  • InsertBefore (XPath) - Inserts the element defined in the web.staging.config exactly before the element defined by the specified XPath passed to “InsertBefore()” transform. In the syntax example the element <allow roles="Admins" />will be exactly inserted before the element <deny users="*" />in the destinationXML.

<authorization>
      <allow roles=" Admins" xdt:Transform="InsertBefore(/configuration/system.web/authorization/ deny[@users='*'])" />
</authorization>

Some advanced points to note:

  • If the Transformation Engine does not find a xdt:Transform attribute specified on a node in web.staging.config file then that node is ignored for Transformation and the Tranformation engine moves ahead traversing the rest of the web.staging.config.

  • A xdt:Transform attribute on a parent can very easily impact child elements eve if there is no Transform specified for child e.g. If xdt:Transform=”Replace” is put on <system.web> then everything underneath <system.web> node will be replaced with the content from web.staging.config

  • It is completely valid to place xdt:Locators attributes on arbitrary nodes inside web.staging.config just for filtering purposes. xdt:Locator does not need to be accompanied with xdt:Transform attribute. (great example here is <location> tag which might just be used for filtering… The example code here would be:

<location path="c:\MySite\Admin" xdt:Locator="Match(path)">>
       
<system.web>
          ... Bunch of transforms written under here will
          .... only apply if location path = C:\MySite\Admin
       
</system.web>
</location>

Step 7: Using Web.config transformation toolset for config files in sub-folders within the project

All of the above discussion directly applies to any web.config file present in sub folders of your project (e.g. if you have a separate web.config file for say “Admin” folder then VS 10 will support transforms for them too). You can add transform files within sub-folders and use the same packaging functionality mentioned in all of the above steps to create transformed web.config files for web.config files specific to the sub folders within your project.

I think this has become a rather long post; but I hope it helps!!

49 comments:

Vishal R Joshi said...

Brianary,
I am attempting to answer your comment inline… Please feel free to write me an email at Vishal.Joshi@Microsoft.com in case you would like to discuss further…
“XDT certainly will be useful to some, but those of us that have a knowledge investment in XSLT or XQuery are going to be very frustrated that there isn't direct support for those languages.”
>>Vishal: XDT has been made completely extensible… I do not remember the exact syntax [I will write a post on that too…] but what transforms like “Replace” etc are doing is accepting the original web.config’s node, accepting the web.transform.config’s node and giving back a new node to the engine… The engine calls all the transforms and the new web.config comes out… The reason for explaining this is coz one of the Transforms (similar to “Replace” etc ) that we were hoping to write was “XSLT” which could take a xsl file and produce the output… It should not be difficult we just never got to it due to time and resource issues… But we certainly have the extensibility and all the inbuilt transforms are written in the same way, implementing the same base classes… If you like we can work together with you to have a community release of “XSLT/Xquery” plugin for XDT… IMHO it will be pretty cool and I am sure many others who have already invested in these technology will benefit from it too… Do drop me a line in case you would like to do so…”
“Sure, for most trivial apps, XDT will produce smaller code (at least than XSLT/XPath 1.0), but size shouldn't be the primary determining factor, or we'd all be programming APL.NET or IronPerl. Besides, XQuery would be even smaller, since it doesn't require the trappings of XML. Shouldn't there be choice of transform language for developers, just as with GP progamming languages? After all, Microsoft isn't killing VB anytime soon, are they?”
>>Vishal: The idea was that for simple stuff 80% of web developers would be able to have good transformation model without huge learning curve and they can continue focussing on building their webs instead of struggling with this aspect of deployment; you will not believe how many people do this manually today due the complexity of XSLT; but nevertheless I agree with you that we should have a way by which you can choose your transform language… Again, we would love to work with you to come up with a model that we can recommend to the rest of the community…
-Vishal

Anonymous said...

Web.config transforms are going to be so useful. It's pretty scary the number of times I've accidentally deployed debug settings to a live site now!

I really wish the same thing could be done for the app.config file in client apps. If anyone's interested, I've opened a request on Connect for this here:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=429336

Vishal R Joshi said...

hi Web Hunter... Yes you can create as many configurations as you want... you can perhaps have web.home.config and create a package out of it... You can read about packaging at http://vishaljoshi.blogspot.com/2009/02/web-packaging-creating-web-package.html... Once you create a SOURCE package out of your home configuration then when you go home and install your web then you will be good to go...
-Vishal

Anonymous said...

Vishal,
I have a Website project. The Context menu does not have an option to 'Add Config Transforms'. Do I have to use the command line approach to create additional config files? We also use Web Deployment projects for web.config transformations in VS2008. They are currently unsupported in VS2010. Do we have to redo our deployment processes now, which used TFS Team Builds and Web Deployment projects?

Thanks,
Mike

Anonymous said...

If xml parsing/xpath performance is important, vtd-xml will be tough to beat

rfeagley said...

Vishal Joshi,
You mentioned in a question on social.msdn.com that it is possible to apply the web config transforms to any well formed XML file within a web application project. Could you go into some detail on what "tweaks" would need to be made? This is an incredibly useful feature which I am very excited to learn more about.

Anonymous said...

is it possible to transform web.sitemap (or any other .xml) files, too? how to set this up for various configuration/packages?

tobi said...

is there a way to transform web.sitemap or any other .xml file, too? how to do that for different configurations (testing, staging, production) sites and packages?

Jack said...

Hi Vishal, great posts.
Is there anyway (using MSBuild command line) I can reproduce the one-click publish tool in VS2010 to publish a web application project to a local file system. I tried the following, the project builds and copies to output folder, but the web.config transform part doesn't copy to the output folder. Any help would be appreciated. Thanks

msbuild myproject.csproj /t:rebuild;TransformWebConfig /p:Configuration=Staging;OutDir=C:\Deployment\Staging\

Jack

Vishal R Joshi said...

Jack, I will try to write a post on how to make one click publish to zero click publish from command line soon... :-)

Vishal R Joshi said...

Tobi... This one is for you http://vishaljoshi.blogspot.com/2010/05/xml-document-transforms-xdt-for-any-xml.html

Vishal R Joshi said...

Rfeagley, hopefully the post http://vishaljoshi.blogspot.com/2010/05/xml-document-transforms-xdt-for-any-xml.html will help...

Daniele Rongione said...

Hi Vishal,
is there a way to apply Transform to a collection of similar elements?
I'd like to replace the encodedValue of a certificate in system.serviceModel/client/endpoint/identity/certificate tag for each endpoint in the web.config without repeating the Transform/Locator.

Vishal R Joshi said...

Hi OsMoSis,
If you can write a generic XPath which can find encodedValue in all the above elements then it would be possible to use the XPath Locator + SetAttributes(encodedValue) Transform to achieve this... Note that when you use XPath locator you do not have to maintain the source web.config schema in web.release.config... Can you possibly give this a try to see if there is generic XPath which can be written for this...
Thanks
Vishal

Daniele Rongione said...

Thank you Vishal for pointing me to the right direction. I was using Replace Transform that doesn't support multiple targets whereas SetAttribute does.
It was simpler than I expected and it doesn't even need Locator.

This is the syntax I used in the transform document (with angle brackets of course):
[system.serviceModel]
[client]
[endpoint]
[identity]
[certificate encodedValue="...." xdt:Transform="SetAttributes(encodedValue)" /]
[/identity]
[/endpoint]
[/client]
[/system.serviceModel]


Just for reference, the XPath that can be used is: /configuration/system.serviceModel/client/endpoint/identity/certificate

Unknown said...

Why is web deployment only available for web application project so far, is lack of .csproj/.vbproj is the reason. We can do connectionString replacement with WebDeployment project in VS2008 and WebDeployment project in VS2010 on Web Site Projects, when can we expect something like web config transformation to work with beyond connectionStrings

Kiran Bheemarti

Vishal R Joshi said...

Hi Kiran
Re: Why deployment features are not available in Web Site projects
Yes, it is correct that the lack of project file and MSBuild support natively within Websites makes it difficult to hook up the deployment system which is natively built on MSBuild...
Although a bunch of deployment features are available within Web Site projects via Web Deployment Projects for VS 2010 which are availabe for download at http://blogs.msdn.com/b/webdevtools/archive/2010/05/26/visual-studio-2010-web-deployment-projects-rtw-available-now.aspx
Do let me know how your experience with that goes...
Thanks
Vishal

Anonymous said...

Is it possible to use this as a Pre or Post Build event? I am thinking no because when I try it as a Pre Build event, it goes into a never-ending build and uses up 100% of my RAM and CPU (talk about burn-in)! Is there some way or should I give up? I'd really like to be able to replace the "CopyIfNewer.bat" technique with config transforms. Each one of our developers has different connectionStrings so we're creating a different Build Configuration for each one (there's only 3 of us now).

Jay Int said...

Vishal,

Does the transform process support configSource references? If I am referencing multiple configSource files in my web.config, would the xml in those external files be accessible to the transformation engine as if it was all included in the web.config?

Thanks. - Jay

Unknown said...

Hi Vishal,

Great post explaining all details about transformations. I know there is no way of applying the transformations locally through visual studio, however as you shown, we can use the /t:TransformWeb.Config flag. Since I am interested in the actual transformation only, is there a way to not have to build the project in order to get the transformations to run?

Thanks

Diego

Vishal R Joshi said...

Late Born,
To transform configSource references check out the blog post http://vishaljoshi.blogspot.com/2010/05/xml-document-transforms-xdt-for-any-xml.html
thanks
Vishal

Anonymous said...

Thank you so much Vishal , Great post with complete explanation.It helped me a lot,I enjoyed reading that

Many Thanks
Naseem

Anonymous said...

Hi Vishal,
Thanks for the nice article.
Quick question, Can we test our transformed web.config using VS?
I am wondering if we can change our environment settings using "Solution Configuration" dropdown box next to "Start Debug" button in tool bar and test our transformed ‘web.config’ file while running in VS.
That would be handy if we can test our configuration before packaging and publishing.

Regards,
Damo

Sayed Ibrahim Hashimi said...

@Anonymous, I recently blogged about how to transform web.config during development. See my blog at http://vishaljoshi.blogspot.com/2009/03/web-deployment-webconfig-transformation_23.html.

Anonymous said...

Hi Sayed,

This is same page you are poining to.
I have another question.
Can we transform web reference url dynamically (of a Class project)? Like our web.config file.
The Web reference is in different Class project.

Thanks,
Damo

Sayed Ibrahim Hashimi said...

@Anonymous, sorry that was user error on my part. The correct link is http://sedodream.com/2010/10/21/ASPNETWebProjectsWebdebugconfigWebreleaseconfig.aspx.
Regarding your second question, if you want to use config transformations outside of Web Application Projects then read my other blog at http://sedodream.com/2010/04/26/ConfigTransformationsOutsideOfWebAppBuilds.aspx.

Vishal R Joshi said...

Q. Since I am interested in the actual transformation only, is there a way to not have to build the project in order to get the transformations to run?
A. Hi Diego, sorry for the hugely delayed response... Here is a possibly wacky workaround... Ofcourse this is not officially suggested but something which will possibly work :-)

1. In a solution containing a WAP, add a new Empty WAP project. (I called mine “TransformConfig”)
2. Delete the default web.config from TransformConfig.
3. Right-click on TransformConfig in Solution Explorer, Add Existing Item…
4. Select (but don’t Add) the web.config and web.*.config files from the original WAP.
5. Click the arrow next to the Add button and choose “Add as Link”. The three files will be added to TransformConfig as references to the existing files, instead of copies.
6. Right click on TransformConfig, Unload Project. Then right click again and “Edit TransformConfig.csproj” (or vsproj)
7. Under each of the transform files, add the following XML: Web.config
8. At the top of the file, change DefaultTargets from “Build” to “TransformWebConfig”
9. Save. Right click on TransformConfig, Reload Project.

Now when you build the TransformConfig project, it will run the transform.
Thanks
Vishal

Anonymous said...

nice posts..

Anonymous said...

I may be missing something here, but how is it better than using configSource property on nodes that change from environment to environment?

Anonymous said...

Hi Vishal, thank you for this very good post. I have now implemented my transformations on my web.config file. My question is about your note on encryption of the web.config file. I have been trying to find a way to encrypt the file before it gets published, but so far I can't seem to get it working. Could you give me some leads on how to do it. Right now I bascially publish my site and then manually encrypt the web.config file using aspnet_regiis call. Thanks.

Vishal R Joshi said...

Hi Anonymous,
AFAIK, unfortunately the web.config file encryption process is still manual today. This is largely because there is a need to decrypt the file afterwards and the app needs to deal with the encryption keys etc. Trying to do this in a global fashion has bunch of shortcomings and hence it was never done at a broad scale in Microsoft.
Thanks
Vishal

Anonymous said...

Hi Vishal.

This is a beautiful blog post :-)
One question: In VS2010
- doing step 5: Generating transformed web.config I get this:
"connectionString="$(ReplacableToken_" when I have a Edm connection.
It does not care about my transform and ruins it.

How do I get rid of the $(ReplacableToken_ in my transformed web.config?

Anonymous said...

HI Good morning

I have VS 2010 Profession edition, but i cannot able to see the “Add Config Trasforms” in my web Application, can you please tell me why it is not displaying

Regards
Praveen

Vishal R Joshi said...

Hey Praaveen, if you right click on your web.config file in Web Application Project (WAP) or MVC Project you should see this.

Note if you are in Web Site project then this option will not be visible.

More info about WAP or WSP at http://vishaljoshi.blogspot.com/2009/08/web-application-project-vs-web-site.html

hope this helps
Vishal

Patt said...

Hi there,

Has anyone try using xdt:locator with condition that use either starts-with or contains?

I.e.,

I have a problem where the compiler thought that there are more than 1 arguments in condition, which prevents me from deploying the project.

Any idea how to work around that?

Thank you,

Patt

Stephen Gross said...

Can you explain at what point in the build process the XML transformation is applied? Is it applied whenever I build the project on my workstation? Or only as part of a Team Build? Or only as part of an MS Deploy call?

Vishal R Joshi said...

Hi Stephen,
At high level you can divide deployment pipeline into 4 pieces "Collection/Build" "Transformation" "Publishing (FTP/MSdeploy etc)".
After all the files are collected then the build is fired and then XML transformations are applied on top of the build output. Finally once the files are ready to be pushed to destination then different protocols for publishing are employed.
That is the reason why web.config transformations work in FTP scenarios as well. When msdeploy is engaged then the XML file is already transformed. If you want additional transformation during installation process then msdeploy parameterization can be used. You can read more about the differences at http://vishaljoshi.blogspot.com/2010/06/parameterization-vs-webconfig.html.
Hope this helps!!
Vishal

IMaReallyBigFish said...

Hi Vishal,

Is it possible to insert XML Comments with the web.config transformations? For example, I like to have comments at the top of the output web.config files that designate the Environment (to make it easier to read for Release Engineers).

For example, I want to add

<!-- QA Environment -->

at the top of the page (directly under the configuration element).

Is this possible?

Thanks,
Felix

Vishal R Joshi said...

Hi IMaReallyBigFish,
You will have to either use Insert transform and insert a dummy empty node with comments inside it or write a custom transform (more cleaner).
They way to write custom transform is documented at http://sedodream.com/SearchView.aspx?q=transform#a27dcfa0d-f88c-4dc3-ace1-0e0d7ef75c1f
Hope this helps.
-Vishal

Unknown said...

Hi Vishal,
In my project I am using external config file for certain app keys from appSetting section (). I have created config transforms for different environments,will config transform change the values of app keys in external config file? If not then how I can change values from external config using config transformation.

Vishal R Joshi said...

Hi Unknown,
You might want to check out http://vishaljoshi.blogspot.com/2010/05/xml-document-transforms-xdt-for-any-xml.html
Thanks
Vishal

Vishal R Joshi said...

Also btw, you might want to take a look at http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5
Thx
Vishal

SecurityGeek said...

RE :Hi Anonymous,
AFAIK, unfortunately the web.config file encryption process is still manual today. This is largely because there is a need to decrypt the file afterwards and the app needs to deal with the encryption keys etc. Trying to do this in a global fashion has bunch of shortcomings and hence it was never done at a broad scale in Microsoft.
Thanks
Vishal


Hello Vishal,

Thanks for the plethora of information on deployment. I have come a long way reading your posts specially everyone's comments. I had a problem similar to "Felix" using Website prjects with WDP. Thanks to both of you I am now able to create deployment packages.
Now I am again in the problem to be able to encrypt, transform and deploy. Since it is not advisable to keep web.configs(specially Production ones) unencrypted, what do you suggest? How can I encrypt my configs, save in TFS and then do web.config transformations and the deploy to various environements. This is big show stopper. Because I cannot sacrifice security for automated deployment packages. Would love to hear what you and others have to say...
Thanks

Unknown said...

Wow,I have been all over the web looking for a simple walk through... Excellent work! YOu should publish a video on PluralSight covering this topic..

Great stuff

Anonymous said...

Thanks for that Blog. It made some important points very clear. Better then the MS-Docs !

said...

Excellent and very useful information, Vishal! Many times in life we have no idea whether the ripples created by our actions produce good or bad results. In this case, you let us leave comments, so you know you have helped many people! Well done!

said...

@Vishal, from your December 1, 2010 post, could you please further explain Step 7? (Under each of the transform files, add the following XML: Web.config) Thanks.

Unknown said...

Hi Vishal

This is a good, informative article. However I still see too many bodged deployments due to invalid settings in .NET web.config or exe.config files.
These include, but are not limited to, dodgy connection strings , references to files that can't be accessed due to permission issues, through to cross-domain connections from a
production server to a database on a developer's machine (very bad!).

This gave me the idea of creating a generic tool for validating .NET config files, which identifies settings within a given config file, and attempts to validate them.
Possible setting types include database connection strings, files, folders, IP addresses, hostnames and URLs - with support for other setting types coming soon.

The tool allows you to perform a number of checks including opening database connections, accessing folders, requesting a particular URL etc etc.
There is a standalone version, but the tool also has Visual Studio integration and a simple API that you can use to embed the tool within your own apps, in order
to perform a config 'sanity check' at app startup time.

I'd be really interested to hear your opinion of my product (CheckMyConfig) - for more info, visit my website below.

Matt

www.checkmyconfig.com

Anonymous said...

Hi Vishal,
my client doesn't wish to see the default generated transformation files (web.debug.config and web.release.config). So I deleted them from project and checked into TFS. But after the build on remote server, these two files appear again.
Is there any way to prevent this behavior?