Showing posts with label web.config transformation. Show all posts
Showing posts with label web.config transformation. Show all posts

Friday, June 18, 2010

Parameterization vs. Web.Config Transformation

I was recently asked about being able to change values of different variables like ConnectionStrings, Installation physical directory, app Settings etc during install time rather than build time, so I thought it might be worth while to de-mystify the concepts around Web.Config Transforms and Parameterization…

Web.Config Transformation

Geeks say Web.Config Transformation is a great feature of Web Deploy (aka MsDeploy), well the first part about being a great feature is true :-) but it is important to note that Web.Config Transformation is not a Web Deploy feature but it instead is a VS 2010 only feature.  Web.Config Transformation is connected with Build configuration of MSBuild/VS/Team Build etc…  Its XML transformation engine is wrapped in MSBuild and has a UI around in VS 2010 which yeilds following benefits:

If you are building a deployment web package (.zip) and know which environment you are building for then web.config transformation is great.  This is the category where many of us fall coz we build for a release environment and need the right config file to go in that deployment package.  For that matter many people are just fine creating web packages for the correct environment they are deploying to…

Now for others who want to be able to build just once and deploy to both test as well as staging/release environment then an embedded web.config file for one environment may not work.  For this scenario there is parameterization.

Parameterization

Parameterization, unlike Web.Config Transform is Web Deploy (aka MsDeploy) only feature, which means that it will not work in non-Web projects or when you are using other protocols like FTP/FTPS etc.  Parameterization from Web Deploy standpoint is a 2 step process

  1. Declare Parameters: You create a Parameters.xml file and pass it to Web Deploy while creating the package…  In this file you need to indicate what file you want to parameterize  (e.g. web.config), what variable inside the file needs to be parameterized (e.g. connectionString) and what would be the default value of the variable (e.g. release connectionString)… Using Parameters.xml file, Web Deploy will create an internal meta data file within your .zip package which guides Web Deploy to know what “Questions” to ask the person who is installing the .zip package… 
  2. Set Parameters: When user is about to install the web package the value of the Parameters can be provided to Web Deploy via several means.  In case you are using IIS Manager to install the package then the IIS Manager UI will automatically show the Parameters with filled in default values.  If you are using Web Deploy command line to install the package then you can provide a setParameters.xml file to the commandline (in case of VS 2010 generated deploy.cmd file just having setParameters.xml file in same folder as the .cmd and .zip file is sufficient).  The setParameters.xml file is a very simple name-value pair file in which you can provide the value of the parameter adjacent to its name.

In one of the future posts I will write more about how to use Parameterization for some canonical deployment scenarios, but hopefully this will lay the foundation of how to differentiate between build time transforms from install time parameters.

Conclusion

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

VS 2010 actually uses a combination of Parameters and Web.Config transforms to provide you with a seamless experience (i.e. connectionStrings, IIS Application Name etc are already parameterized by default) so for most common scenarios you would hopefully not have to delve into understanding all the details but if you have any questions then of course feel free to ask here or via email…

Thanks

Vishal

Tuesday, May 18, 2010

Applying XDT magic to App.Config

For several weeks now people have been asking to be able to use the XML Document Transform (XDT) with App.Config files similar to what is available with Web.Config files in VS 2010…
In all honesty there is no official/supported  implementation of XDT for any other project type than Web Application Projects but the good news is that the basis of Web.Config Transformation resides in Web Publishing Pipeline (WPP) which are set of extensible tasks and targets hooked up to provide a great deployment story for Web Applications…
Today, Ming (our senior dev on Visual Studio) and I decided to get together to give some love to App.Config file too… The below implementation is a crude way of getting XDT working into other project types within VS 2010… In a way, I would say it is a big solution for a smaller problem but the idea here is to get people unblocked and show the kind of things that WPP is capable of doing… 
If by now everything is sounding foreign then please check out the articles:

  • Web.Config Transformation
  • VS 2010 Snippets for Web.Config Transformations
  • Web.Config Transforms (XDTs) for any XML files in your web projects
    Goals
    • Being able to use XDT syntax for App.Config files similar to what you can use with Web.Debug.Config and Web.Release.Config…
    • Being able to use this in an automated fashion in build environments like Team Build…
    • Reduce the concept count and make it as simple as possible (without digging deep into optimization & performance)…
  • Please take a look at Visual Studio extension which allows you to do this without the manual workarounds below:
  •  http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5

    Step by Step Instructions

    The example I am using below should be hopefully super simple that you can follow along without any prep work… All you need is VS 2010 which has “Visual Web Developer” components installed…

    Step 1 Create a new Windows Forms Application in VS 2010

    Step 2 Add App.Config file to the project…

    Add simple test settings to App.Config file as shown below:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="author" value="Vishal Joshi"/>    
      </appSettings>
    </configuration>




    Step 3 Add App.Debug.Config file to the project, I would recommend using the same App.Config file adding mechanism as shown below




    app.debug.config



    Step 4 Modify the content of App.Debug.Config as shown below:



    <?xml version="1.0"?>
    
    <!-- For more information on using App.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
    
    <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
      <appSettings>
        <add key="article" value="XDT Magic for App.Config Files" xdt:Transform="Insert"/>
      </appSettings>
    </configuration>





    The key things to note above are:





    • There is a XDT namespace declaration which allows XDT engine to recognize the Transform/Locator syntax in the file


    • There is a new node being inserted into the config file using the syntax xdt:Transform=”Insert”




    Step 5 Save the edited files and unload the project frin VS 2010 Solution Explorer using the right click command as shown below:



    unload project




    Step 6 Edit the .csproj/.vbproj file to make App.Debug.Config file to be dependent on App.Config file as shown in the syntax below:




        <Content Include="App.config" />
        <Content Include="App.Debug.Config" >
          <DependentUpon>App.Config</DependentUpon>
        </Content>





    The key things to note above are:





    • By default the build action of App.Config and App.Debug.Config file will be “ None”… It needs to be changed to “Content”… This is a tiny pre-requisite for WPP but if you encounter any issues because of this then we can dig the work around…


    • DependentUpon node will make your App.Debug.Config appear as a node under your App.Config file similar to the way Web.Debug.Config and Web.Release.Config files appear under Web.Config file…


    • In VB Projects nested files are hidden so you might need to unhide these by clicking the icon on the solution explorer…




    Step 7 Change the ProjectConfigFileName property within your .csproj/.vbproj file



    WPP has an inbuilt property called ProjectConfigFileName which is by default set to Web.Config, we need to change this to app.Config which will allow projects like WinForm project not expect web.config files to transform… You can add this property right under ProjectGuid property as shown below:



      <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
        <ProductVersion>8.0.30703</ProductVersion>
        <SchemaVersion>2.0</SchemaVersion>
        <ProjectGuid>{2D587604-866B-4675-8587-FA9728EC59D8}</ProjectGuid>
        <ProjectConfigFileName>App.Config</ProjectConfigFileName>




    Step 8 Hook up WPP within your WinForms project by importing the WPP targets.



    You can search for “Import” node in your project file and then simply copy below one line for WPP targets import



      <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />





    Step 9 Add a target to copy the transformed App.Config file to your output (BIN) directory




    You can simply copy paste the below code just before your </project> node closes in the .csproj/.vbproj file



      <Target Name="PostTransformAppConfig" AfterTargets="TransformWebConfig">
        <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" 
              SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" 
              DestinationFiles="$(OutputPath)\WinFormConfigTransform.exe.config" />
        <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" 
              SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" 
              DestinationFiles="$(OutputPath)\WinFormConfigTransform.vshost.exe.config" />
      </Target>





    The key things to note above are:





    • We hooked up the new PostTransformAppConfig target after TransformWebConfig target… The TransformWebConfig target is the native target in WPP which does any XML transform and will do the actual job of transforming App.Config as well..


    • The location at which the new App.Config file is getting copied is pretty self explanatory but do note that you do want to change “WinFormConfigTransform” to be the name of your own Project…  I just used a project called “WinFormConfigTransform” and hence the DestinationFiles path is named as such…




    Step 10 Run /T:TransformWebConfig task on your Project from MSBuild



    You need to use Visual Studio 2010 Command prompt and type in the below command



    msbuild C:\Vishal\WinFormConfigTransform.csproj /t:TransformWebConfig



    After running the above command if you now check the BIN folder of your project you should see that the Project.exe.Config file is now modified as shown below:



    image 



    NOTE: If you want the App.Config file to be Transformed after every build in your Visual Studio IDE (this will take some perf away but may not even be noticeable) then you can change Step 9 code to be as below:



    <Target Name="PostTransformAppConfig" AfterTargets="Build">
        <CallTarget Targets="TransformWebConfig"/>
        <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" 
              SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" 
              DestinationFiles="$(OutputPath)\WinFormConfigTransform.exe.config" />
        <Copy Condition="Exists('$(TransformWebConfigIntermediateLocation)\transformed\App.config')" 
              SourceFiles="$(TransformWebConfigIntermediateLocation)\transformed\App.config" 
              DestinationFiles="$(OutputPath)\WinFormConfigTransform.vshost.exe.config" />
      </Target>



    The only key difference above is that I made the new target to be called after “Build” and in the new target I made a call to “TransformWebConfig” target to ensure the transform happens before we try to copy the transformed app.config file to their final location…




    With the above change now when you build in IDE then the new transformed App.Config will be copied to your output directory…



    With the above 10 steps you should now be able to Transform your App.config just like the way you do Web.Config files in VS 2010



    -Vishal



    PS:  Whenever you make changes to your project file (like above) you make your project susceptible to data loss during upgrade to future versions of VS as next versions of VS will not know all the fancy code you put in the files, but such risks are part of the game to get all the fancy toys working :-)

    Sunday, May 02, 2010

    Xml Document Transforms (XDT) for any XML file in your project

    There have been several requests floating around to be able to use XDTs (the technology behind Web.Debug.Config/Web.Release.Config) with other XML files within the project…  To make that feasible I wrote a XmlDocumentTransform.targets  file which can generically transform any XML file using the standard Web.Config Transformation syntax introduced with VS 2010…

    Learn more about XDT & Web.Config Transformation here…

    Now to get started first download XmlDocumentTransform.targets file from my Skydive…

    Follow the below simple steps to get transformation working for any well formed XML file in your project…

    • Step 1: Save the downloaded XmlDocumentTransform.targets to %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v10.0\Web\XmlDocumentTransform.targets

    image

    NOTE: I would highly encourage you to make a copy of the Microsoft.WebApplication.targets file as backup before you do Step 2 below, as if this file is modified incorrectly then your VS 2010 instances might start showing funny problems which will be virtually impossible to debug and the only option left with you will be to repair/uninstall-install VS 2010… (i.e. proceed at your own risk :-))

    •  Step 2: Put following line of code in Microsoft.WebApplication.targets file just before closing of the Project node i.e. before </Project>...  
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\XmlDocumentTransform.targets" Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\XmlDocumentTransform.targets')" />
      The Microsoft.WebApplication.targets file is located at %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications... 

    image  
    NOTE: Changing the above targets file will allow you to use this functionality with all the Web Application Projects (WAPs), if you just want to change this for the current project then you can put the same Import node in .csproj or .vbproj as well...  If you use per project model then you can also check in this file into source code control and have your team use it seamlessly…

    • Step 3: Open your .csproj/vbproj file and insert the below property in <PropertyGroup> section  <AllXmlsToTransform>Settings.xml;app.config</AllXmlsToTransform>

    image

     NOTE: The Settings.xml or app.config can be replaced with the name of Xml files you want to transform…

    • Step 4: Insert <OnAfterTransformWebConfig>TransformXml;</OnAfterTransformWebConfig> similar to #3 above but do not modify the TransformXml; text here…  This is the actual hook which ties in your project to this generic XDT system...  After making the Step 3 & Step 4 changes your project file should have below content…

    image

    • Step 5: Create Setting.Debug.Xml or similar files and put XDT syntax in them... You need to make sure in the .csproj/.vbproj file of yours you have the DependentUpon property is set like the example below:
          <Content Include="Configuration\Settings.xml" />
          <Content Include="Configuration\Settings.Debug.xml">
            <DependentUpon>Configuration\Settings.xml</DependentUpon>
          </Content>
          <Content Include="Configuration\Settings.Release.xml">
            <DependentUpon>Configuration\Settings.xml</DependentUpon>
          </Content>

    image

    NOTE: The above will allow your solution to look pretty, i.e. just like web.debug.config and web.release.config files show nested under web.config, your *.$(configuration).* files will show nested under your parent file too…

    With the above 5 steps you are all set to use XDT with any of the deployment models covered in the Overview of Web Deployment Post…  In a way above steps harness the power of Web Publishing Pipeline (WPP) extensibility model and you can do several other extensions like above if you are familiar with MsBuild sytax…

    SAMPLE:   The remainder of the post is just showing you the steps to test whether the changes you made worked or not (i.e. the remaining half of the post is just playing with what you already accomplished in the first half)… :-)

    • To test the above target file I created the below MVC 2.0 project structure:

    image

    • Once you put DependentUpon node in your project file you will have to click the  “Show All Files” icon on the solution explorer for VB Projects to see Settings.Debug.Xml
    • My Settings.xml file looked as below:

    image

    • My Settings.Debug.xml file looked as below:

    image

    • To test out I tried simple “file system” publish (Right click on project and say Publish)… The new WAP Publish dialog for me looked as below:

    image

    • After publishing my C:\TestPublish folder looked as below:

    image

    • Note that Settings.Debug.xml was removed from my final publish location as it is not required for my web to function and the content of Settings.xml file were transformed and looked as below:

    image

    TeamBuild/Commandline Approach: You can also use your new transformations from TeamBuild/MsBuild by using the below command (from VS 2010 Command prompt if you are trying locally):

    MsBuild MyXDTTestProject.csproj /t:TransformXml

    The output of the command line transform should look as below:

    image

    As specified above your transformed XML will be stored in obj\$(configuration)\Settings.xml… 

    As such feel free to open the XmlDocumentTransform.targets file which you download, I have tried to put as much comments as I could to make it readable…  If you go through it I am sure you will be able to do many other cool things out of it…

    -Vishal

    Monday, April 26, 2010

    Xml Document Transform (XDT) Snippets for VS 2010

    During my PDC talk I had shown some of the snippets that can come handy while using Web.Config Transformations…  This post is intended to share the XDT snippets and instructions on how to install them to use them with VS 2010…

    image

    • After this the XDT snippets will be available for you to use within any XML file within VS 2010…

    To know how to use XDTs for Web.Config file please check out the post about Web.Config Transformations

    Few interesting points about Transforms & Locators which are worth noting to do pretty powerful stuff with your XML are:

    • Transforms  - Transforms act on a XML node i.e. from XDT engine standpoint the node on which a transform is found is plucked out of the document and passed as a node to the Transform itself (e.g. “SetAttributes” Transform)… The Transform class internally implements the logic of modifying the node with its own special logic (i.e. setting attributes in case of “SetAttributes” Transform) and returns back the node to the engine…  The XDT engine then replaces the new node into the document…  The engine also passes the handle of the parent node to the transform which the transform can then play around with (e.g. “Insert” Transform receives a new node as well as the parent node and has the DOM code of inserting the new node under the parent…)

    image

    • Locators – XDT usually traverses through the XML document and constructs the XPath all along e.g. when it hits the add node under connectionStrings in web.config it has already constructed the XPath (/configuration/connectionString/add)…  Locators help with narrowing down the XPath so that the correct node can be picked up… Check out the example below:
       <connectionStrings>
    <add name="1stDB"
    connectionString="Data Source=Server1;Initial Catalog=DB1;Integrated Security=True"
    xdt:Transform="SetAttributes" />
    <add name="2ndDB"
    connectionString="Data Source=Server2;Initial Catalog=DB2;Integrated Security=True"
    xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>




    Based on the standard logic of XPath traversing XDT will always pick up the first “add” node i.e. one with 1stDB in the example below… That may not be always desirable…  In XDT we could have implemented the logic to do special things for appSettings & connectionStrings but then that would have made XDT specific to web.config instead we implemented Locators which now allows XDT to be general purposes XML transformation engine…  In the above example if we use a Locator called xdt:Locator=”Match(name)” on the 2ndDB then as soon as the XDT engine encouters a locator it calls the class implementing it (i.e. “Match” and allows it to play with the XPath that is being generated… In this case the match locator will help construct the XPath as /configuration/connectionString/add[@name=’2ndDB’]



    xdt:locator



    The high level takeaway here is that when you play around with the snippets for XDT keep the above concepts for Transforms & Locators in mind and with the quick snippet explanations of each transforms and locators you should be able to very easily use all of them… If you encounter any issues plz feel free to reach out…



    Thanks!!



    -Vishal



    Sunday, May 31, 2009

    Web 1-Click Publish with VS 2010

    Visual Studio 2010 has great features to make your web deployment easier…   I have written a high level article describing the web deployment feature set of VS 2010 below:

    Today my goal is to go through an end to end walkthrough of the Web 1-Click  Publish feature of VS 2010…  This walkthrough will cover following:

    • Prepping up an ASP.NET 4.0 web application which is using a SQL Server Database for deployment
    • Gathering the remote web and database server information
    • Setting up Web.config Transformation to change your connectionString
    • Including SQL Server Databases in Web Deployment
    • Creating a 1-Click Publish Profile to Publish your web content, databases and transformed web.config files
    • 1-Click Publish your Web Application

    For this walkthrough you will need Visual Studio 2010 Beta1 which you can download FOR FREE from http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx

    Let us get started…

    Prepping up an ASP.NET 4.0 web application which is using a SQL Server Database for deployment

    In this walkthrough we are assuming that you already have a web application which uses SQL Server database and you are ready to deploy it to remote web server and database server…  If you do not have such a web application then I encourage you to follow the simple step by step instructions in the walkthrough Creating a simple .NET 4.0 web application using Visual Studio 2010…

    With the assumption that you now have a data driven ASP.NET 4.0 web application let us try to understand what all is needed to be taken care of while deploying such a web application… Things that you need to take care of during such typical deployments are:

    1. You need to modify the connectionStrings in the web.config file to point to the remote SQL database server instead of the local SQL Server Express that you are using on your dev box…
    2. You need to deploy your databases to the remote SQL database server
    3. You need to deploy all of your master pages, content pages, images etc to the remote web server

    In the remaining portion of this walkthrough you will see how to accomplish all of the above things…

    But before getting to that, let me introduce you to Web Application we are about to deploy… The solution explorer of this web application looks as below:

    1-ClickPublish solution explorer

    Notice that this web application has 1-ClickPublish.mdf file in the App_Data folder…  Also notice that it has a Site.Master, Default.aspx and Address.aspx Web pages…  When you run Default.aspx it looks as below:

    Default.aspx

    The top banner of “Visual Studio 2010 Web 1-Click Publish” is coming from Site.Master…  The grid containing FirstNames & LastNames is being populated from the 1-ClickPublish.mdf file…  The “View Addresses” button takes you to “Address.aspx” page which shows the addresses of the people on “Default.aspx” as shown below:

    Address.aspx

    The web.config file of this web contains connectionString named “1-ClickPublishDB” which points to the SQL Server express database (1-ClickPublish.mdf )…

    Gathering the remote web and database server information

    Before we begin to deploy the web application to the remote server we will need to gather the information of the destination servers… Typically if you are going to a shared hoster then this information is provided to you in the welcome email from your web hosting company…  Web hosters typically have various plans which include database as well as web server storage space….

    If you are not planning to go to web hosting company but rather are interested in hosting your own web and database servers then you will have to follow some more additional steps to set up your web servers and database servers…  I am not covering this in the current walkthrough but will cover the same in subsequent walkthroughs…  But for now let us assume you have a web hoster who has provided you with the information required for deployment…

    Typically web hosters will ask you which .NET Framework version you would like to target (i.e. 2.0, 3.0, 3.5 or 4.0)… Based on the .NET Fraemwork version you choose your web site will be provisioned with the correct Application Pool… For .NET 2.0, 3.0 and 3.5 the Application Pool targets CLR version 2.0… For .NET 4.0 the Application Pool is set to CLR version 4.0…. It is very likely that your .NET 2.0, 3.0 or 3.5 web application will run seamlessly on .NET 4.0 but it is still required to talk to your hoster to change you Application pool from .NET 2.0 to .NET 4.0… 

    If you register for a hosting plan which supports the new VS 2010, ASP.NET 4.0 and Microsoft Web Deployment Tool (MsDeploy) then you will receive below pieces of important information which we will use later during the walkthrough… In the rest of the walkthrough I will refer to these as “1-Click Settings” so that you can easily relate to this section…:-)

    • Service URL:  This URL is in the format https://myWebServer:8172/MsDeploy.axd and actually points to a IIS handler which will manage your deployment on the remote web server
    • Site/Application Name: This is the name of your IIS Web Site on the remote web server…  This is where your application will be deployed…
    • UserName: This user name is the account which has the access to the ServiceURL and your Site on the remote web server
    • Password:  The password which you use for your above UserName
    • ConnectionString: This is the ConnectionString to your remote database server… Typically your hoster will make sure that your remote web server and remote database server have the correct ports opened so that your web application can easily consume the data from your database…

    At this time I am assuming that you have your web application ready to be deployed and you already have the above pieces of information from your web hoster…  The next thing we will do now is to set up web.config transformation to modify your web.config file during deployment….

    Setting up Web.config Transformation to change your connectionString

    Let us assume that you are using “Release” build configuration when you are deploying to a remote web server…  You can create and use a different build configuration as well but I am choosing “Release” as it comes out of the box with VS 2010…  Learn more about Managing Build Configurations… 

    By default “Debug”  is the ‘Active’ build configuration… As we are ready to deploy to a hoster you can change your Active build configuration to “Release”… You can do so by simply changing the drop down value on the VS “Standard” toolbar as shown below:

    build configuration

    Alternatively you can also change the build configuration by going to the Build –> Configuration Manager menu…

    After this step your Active Build Configuration should be “Release”…  You can now open up the node next to the web.config file to reveal web.debug.config and web.release.config as shown below:

    web.release.config

    In case of VB.NET you will have to click the top right button to “Show all files” to see the dependent web.release.config…

    Now open the web.config as well as web.release.config files and copy the connectionString section from the web.config file into the web.release.config file as shown below…

    FROM

    web.config connection string

    TO

    web.config with connection string

    Now you need to do two quick things

    1. Just simply write xdt:Transform=”Replace” in the connectionString node of web.release.config as shown below…
    2. Also change the connectionString attribute by putting the value that you got from the hoster (the one we referenced in “1-Click Settings” )… Let us say my hoster proived me with connectionString as “Data Source=myHostedSQLServer;Initial Catalog=myhostedDBName; User ID=VishalRJoshi; Password=*VS10Rocks” then my web.release.config should look as below…

    final web.release.config

    Also note that by default Web.Release.config has a transform called “RemoveAttributes” to remove the debug attribute when you are going to the “Release” environment…  Many hosted environment will not allow you to have debug=true coz it is not safe hence removing the debug attribute is required…

    With this you have set up the automated web.config transformation which will take care of changing your connection string during every deployment… !! There is a lot more you can do with XML Document Transforms (XDT)…  Check out the different possibilities Web.Config Transformations by leveraging XDT here…

    Including SQL Server Databases in Web Deployment

    As the current web application is actually using the data in 1-ClickPublish.mdf it is required to move the database schema and data from this local SQL Server Express database to remote hosted SQL Server database server… In order to make that happen you need to go to “Deploy SQL” tab of the Project properties…

    You can open project properties by double clicking the “Properties” item under the project node as shown below:

    image_thumb10[2]

    When project properties window opens then navigate to “Deploy SQL” tab…Once you open “Deploy SQL” tab you need to do following quick things:

    Make sure you are using the “Release” configuration as that is the configuration we are going to deploy (and you also have web.config transformation for Web.Release.config)…

    Click “Add” button and give a friendly name for your database deployment as shown below: (I would recommend using the name that you used for your connectionString – for secret reasons I will talk about in future posts :-))

    Add new connectionString

    Next you will have to configure the “1-ClickPublishDB” settings which you just created by clicking it…  As soon as you click it the disabled section below will light up which you need to fill in as shown below…

    Deploy SQL tab

    The key points to note while filling up the DB Deployment information above are:

    • ConnectionString for the destination database is the connectionString which you received from hoster in an email (the one we referenced in “1-Click Settings” )…
    • “Pull data from an existing database” will instruct Visual Studio 2010 to extract data from the local SQL Server…
    • The connection string below the “Pull data from…” checkbox represents the source database (which is on your local dev box)… This connection string can be found in the original web.config file of your web application as the datasource controls you used insert the connectionString in web.config file…
    • The “Complete database” radio button instructs Visual Studio 2010 to script both database schema as well as data from your database…  If you contain junk data that you do not want to deploy to the server then choose “Shema only” option…

    With these settings you can now hit save on top of Visual Studio and you have configured your database for deployment as well…Hopefully that was not too hard :-)  If your needs are more deeper than the above then there are many other powerful Database Deployment options which I have discussed in DB Deployment post earlier…

    Creating a 1-Click Publish Profile to Publish your web content, databases and transformed web.config files

    Now that you have set up web.config transformation and also set up you database deployment settings, it is time to create a 1-Click Publish profile to use for your deployment…

    You can do so by Right clicking on your project node and hitting “Publish…” as shown below:

    Right Click Publish

    With that you will get the “Publish Web” dialog which you can fill as below:

    Publish Dialog

    I have specially numbered the fields above so that you can easily relate to them in the text below:

    1. Publish Profile Name-  I have named it as myWebHosterName you can name it with the destination name that you can easily remember…  Usually if you are going to a web hoster then naming this as something like “DiscountAsp” or “OrcsWeb” would be advisable…
    2. Service URL:  As we discussed in the “1-Click Settings” section at the beginning of the post, this is provided to you by your hoster…  This URL associated with the Publish Method “MsDeploy” which is used behind the scenes by Visual Studio 2010 to Publish your entire web… You can learn more about the way MsDeploy works in one of my previous blog posts…  Also while you are at it note that the new “Publish” dialog also tells you the Build Configuration that you are publishing (i.e. the Active Build Configuration), in our situation we are using the “Release” configuration for which we have set up the DB Deployment and Web.config transformation…
    3. Site/Application Name: As we discussed in the “1-Click Settings” section at the beginning of the post, this is also provided to you by your hoster…  If your hoster provided VishalRJoshi.com as your Site name you can feel free to append a folder name underneath it e.g. VishalRJoshi.com/Blog…
    4. Mark Folder as IIS Application on destination: If you choose to Publish to a folder under the parent site eg “VishalRJoshi.com/Blog” AND  want to have separate session state, cache etc functionality for that subfolder then you will have to convert that folder into an IIS Application underneath your parent web site…  This checkbox will allow you to achieve that easily in an hosted environment… This is a the additional IIS enhancement that was made as part of “MsDeploy” Publish Method, so we hope you will like it…:-)
    5. Allow untrusted certificates-  MsDeploy Publish method will only take https:// URLs… As you know that secure http requires a SSL certificate but it is understood that it will not be possible to always buy a certificate from authorities like VeriSign etc and especially if you are deploying within your team environment then expecting a fully signed certificate may not be rational, hence this option allows the web server owner to provide a self signed SSL certificate… Although, in general it should be understood that checking this box increases threat on the data which is being transferred over the wire…
    6. User Name, Password and Save Password:  Again, As we discussed in the “1-Click Settings” section at the beginning of the post, User Name and Password is also provided to you by your hoster…  “Save Password” is a feature in VS 10 which will securely save your password, so that you do not have to keep typing it again and again…
    7. Save -  Now you can hit the Save button on the top, to save the “Publish Profile” you just created…
    8. Close – Close button will allow you to close the “Publish Web” dialog

    After doing all of the above you have configured your Web Application for 1-Click Publish going forward…

    1-Click Publish your Web Application

    For your convenience Visual Studio 2010 offers Web 1- Click Publish toolbar as shown below:

    image

    You can enable this toolbar (if not visible) by going to View—>Toolbars—> Web One Click Publish… You can now simply click the Publish button below after every little change you make to your project that you want to deploy… 

    image

    This way you can keep updating your web at the destination with ease…  Do note that you are allowed to have upto 50 Publish profiles per project, which can allow you to Publish the same project to 50 different web servers in just clicks (I hope 50 should be enough, if not let us know now and we will be happy to bump that up :-))…

    NOTE:  If you are incrementally publishing you web then you should go to “Deploy SQL” tab and uncheck your database deployment… If you do not do so then your Publishing will fail as MsDeploy intentionally does not overwrite the database that you already have on the server…  There is a easy fix to change that behavior i.e. there is an option to delete database every time you republish, but I will refrain from mentioning it until someone asks as that is purely a Test server scenario… :-)

    Checking your deployed Web

    With all of the above steps you are good to hit the “PUBLISH” button…  Once you hit the button your web should get deployed to the hoster much more quickly and reliably than ever before…

    With all this you are now set up to have 1-Click Publish of your web application from Visual Studio 2010…

    In later posts I will share the Performance and Scalability numbers of MsDeploy Publish method too but as far as I can tell MsDeploy publish is quite more reliable and performant than most other traditional web publishing mechanisms…

    I hope this walkthrough will help you experience the new powers of Visual Studio 2010 and Microsoft Web Deployment Tool…

    If you would like to learn more about Web Deployment with VS 2010, then I have explained a bunch of other features in the posts below:

    Hope this walkthrough is helpful

    -Vishal

    Some KB Items:  There are certain known issues and workarounds which you may or may not encounter but I have still posted them here in case you face any of those… Known Issues, Resolutions and Work-Arounds for VS 10 Web 1-Click Publish…

    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!!