Setting Up Additional Configurations and the Files

When creating a new web application project in ASP.NET 4, the web.config is included as expected, but so are two additional files as seen below.

image

If you don’t see them initially, expand the collapsed entries by clicking on little black arrow to the left of the Web.config filename.

What each file does will be disgusted later on, but first let’s see how to add more files. If you right-click on the web project and go through the menu to add a new item and select Web Configuration File, you will not get a file automatically associated like the Debug and Release files seen above. It will look like the following.

image

To have things work nicely, the build configurations should be set up first. Go through the toolbar or whatever process you like best to edit the build configurations.

image

This will provide us with the popup to create new build configurations.

image

In the next window, fill in the settings that are appropriate for your new configuration. For example, Testing, Staging, etc.

image

After doing this and reloading the project file, the Web.Testing.config still doesn’t fit into the collapsible Web.config area. This is because it was added before the build configuration, so make sure to add the build configurations first! If you find yourself in this situation, you can manually edit the project file to create the association.

After opening up the project file for editing and searching for Web.config, we find the following.

  <Content Include="Web.config">
    <TransformOnBuild>true</TransformOnBuild>
  </Content>
  <Content Include="Web.Debug.config">
    <DependentUpon>Web.config</DependentUpon>
    <IsTransformFile>True</IsTransformFile>
  </Content>
  <Content Include="Web.Release.config">
    <DependentUpon>Web.config</DependentUpon>
    <IsTransformFile>True</IsTransformFile>
  </Content>

Notice the difference for the Debug and Release files? Where is the Testing entry? Searching for it in the project file, it’s found as a normal file entry.

  <ItemGroup>
    <Content Include="Web.Testing.config" />
  </ItemGroup>

You can manually remove the ItemGroup entry for the Testing file and create a Content entry that mimics the Debug and Release entries.

  <Content Include="Web.config">
    <TransformOnBuild>true</TransformOnBuild>
  </Content>
  <Content Include="Web.Debug.config">
    <DependentUpon>Web.config</DependentUpon>
    <IsTransformFile>True</IsTransformFile>
  </Content>
  <Content Include="Web.Release.config">
    <DependentUpon>Web.config</DependentUpon>
    <IsTransformFile>True</IsTransformFile>
  </Content>
  <Content Include="Web.Testing.config">
    <DependentUpon>Web.config</DependentUpon>
    <IsTransformFile>True</IsTransformFile>
  </Content>

After saving the changes and reloading the project file, the association for Testing is correct.

image

Generating the Transformed Configuration Files

At this point, it’s easy to see that the middle portion of the filename corresponds the build configuration. What does it actually do? By default, the deploy will produce a transformed configuration file. This doesn’t happen for normal build operations and debugging, like hitting F5. Take a note here that the Web.Debug.config entry will not be transformed into your debugging web.config file when running in Visual Studio. Without the extension mentioned below, this would only be for deploying the application in debug mode. We will see with an extension that this is possible though. After setting up a Publish entry in One-Click Publish and deploying it to a local file system folder, the following can be seen when Show All Files is selected for the project.

image

Notice the path objTestingTransformWebConfig and then the original and transformed directories. Comparing the two Web.config entries at this point will show the differences, if any.

Using the Transformation Syntax to Produce Custom Settings per Build Configuration

There are a variety of ways to apply transformation, but the two I find myself using most often are Replace and SetAttributes. Here are some examples:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <elmah>
    <errorLog
      name="ElmahConnectionString"
      connectionString="Data Source=dbserver;Initial Catalog=dbname;User id=username;Password=password;"
      xdt:Transform="SetAttributes"
      xdt:Locator="Match(name)"
      />
    <errorMail
      name="ElmahMailSettings"
      to="no-reply@devtreats.com"
      xdt:Transform="SetAttributes"
      xdt:Locator="Match(name)"
      />
    </elmah>

  <appSettings xdt:Transform="Replace">
    <add key="RemoteServerIP" value="127.0.0.1" />
    <add key="RemoteServerPath" value="." />
  </appSettings>

  <connectionStrings xdt:Transform="Replace">
    <add name="MyConnectionString" connectionString="Data Source=dbserver;Initial Catalog=dbname;User id=username;Password=password;" />
    <add name="CsvConnectionString" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties='text;HDR=Yes;FMT=Delimited';Data Source="/>
  </connectionStrings>
</configuration>

The ELMAH connection string and mail settings are using the SetAttributes transform by matching on the name of the attribute. The result of these operations will change the attribute values for connectionString and to, respectively. For the appSettings, the Replace transform type is used to swap out the whole appSettings section. You could handle these in different ways, but I find that usually all or most of the appSettings values change per build configuration type, so I simply replace the whole thing rather than adding transform syntax to each line.

What this provides is a way to set any number of configuration changes based on the build configuration. As shown above, the connection strings don’t have to be worried about and changed when doing different deployments. You can set it and forget it, for the most part.

Please reference MSDN for the full documentation on transformation syntax: http://msdn.microsoft.com/en-us/library/ie/dd465326.aspx

That Works for ASP.NET web.config files, But What About the app.config files?

Unfortunately, it’s not directly built into Visual Studio/MSBUILD, but there is an excellent extension available for free called SlowCheetah – XML Transforms. This extension allows for not only doing these same types of operations on app.config files, but it allows for transformations of the config files during Visual Studio debugging. Bring on F5 integration! It even works for any XML file within your projects. For example, I often have a logging.debug.config and a logging.release.config to keep my web.config or app.config clean. This extension allows for transformations of those files perfectly and outputs them into the bin directory.

It also allows for previewing of the transformations when you right-click on one of the transformation XML files.

Conclusion

The built in functionality is long overdue and a much nicer implementation than using the Enterprise Library dynamic changes feature they added around version 3. There are some other tools available as well, but having it built in reduces the guess work and cross-training. Throw in the SlowCheetah extension and it’s pretty feature complete. Hopefully the Visual Studio team incorporates SlowCheetah’s features in vNext.

Happy Transformations!

I have found that having all projects expanded by default can be annoying, as I tend to open solution files when working in Microsoft Expression Blend.  This often leaves me having to collapse each project individually.  Within Visual Studio, I use PowerCommands for VS2010 and PowerCommands for VS2008 to provide the collapse-all functionality and it works great.

Since Blend 4 uses MEF, I set out on writing an extension to provide this functionality.  I learned how to begin with How to Hack Expression Blend.  The most helpful article I found was Building Extensions for Expression Blend 4 Using MEF by Timmy Kokke.  Following his startup example, I was able to use the debugger and figure out how to interact with Blend’s various parts.  I put forth some effort to have a dropdown menu or button added to the right of the Help entry, but I haven’t finished that exercise yet.  Ideally, I would like to have an entry added to the context menu of the Projects window when right-clicking on a solution or project file.  In the mean time, I have it working with a docking window.

Step 1: Installation

Download (DLL only):

Extract the extension DLL to the folder location “….Program Files (x86)Microsoft ExpressionBlend 4Extensions”.  You may have to right-click on the DLL and click the Unblock button.

Step 2: Using the Extension

After a successful installation, the Window dropdown menu should contain an entry for Collapse All Projects.  As you can see from the screenshot, I have configured the extension to use Ctrl+Shift+C as a shortcut.

Collapse All Projects Menu Entry

Once the menu item is selected, a popup window should appear.  This window is like the Projects, Properties, Assets, etc. windows within Blend, which means you can dock it.  I’ve chosen to dock it to the bottom as shown below.

Collapse All Project Window Docked

Hovering over the window shows the contents.  Simply click the button for the collapse all to be applied.

Collapse All Project Window Expanded

That is it!  If you find any bugs or issues with this, please let me know.  If you get around to making it a context menu item or as a main entry of the top dropdown menu, please share.

Tools Used:

  • Reflector
  • Snoop
  • I wanted to use Mole, but was developing in VS2010.  It doesn’t appear there is a compatible version yet.  Speaking of which, I would really like to see Mole for Silverlight.

Download the Source: