Transform web.config file when creating a release branch - visual-studio

We essentially have two separate development paths:
Local → Dev → QA → Prod
Local-Release → Dev-Release → QA-Release → Prod
The first path uses our mainline/trunk, the second path is for when we cut a release branch and need to make bug fixes in between releases.
We use config transformations for Dev, QA, Prod, Dev-Release, and QA-Release and this all works great. However, after each time we cut a release branch, we have to manually change the config files for the Local-Release environment (things like changing the connection string from using LocalDB to LocalReleaseDB, etc).
It would be ideal if we could automate this using another transformation file, but we're not publishing anywhere. Is there a trick to get around this? Could we do it at runtime or have a powershell, batch file, or something else run after creating the branch? What do others do to accomplish this?

I believe that SlowCheetah will give you what you need.
Taken from the SlowCheetah website:
This package allows you to automatically transform your app.config (or any file) when you press F5 in Visual Studio. You can have different transformations based on the build configuration. This will enable you to easily have different app settings, connection strings, etc for Debug versus Release. If you want to transform other files you can do that too.
I haven't ever tried this in a TFS build scenario, but as long as SlowCheetah is installed on the build servers, I guess it would work.

I believe I found a viable solution here: http://kfigy.blogspot.com/2010/03/making-visual-studio-2010-webconfig.html
He's using the approach to allow multiple developers to each have their own config settings, but it can also be used to have config settings per branch.

Related

Visual Studio not running correctly transformed config file

My approach here may be wrong, so apologies if so - I'd appreciate any advice on what I did wrong.
I need to run (locally, for debugging), a specific configuration of a project that contains specific web.config transforms.
In my solution, in Configuration Manager I have the following listed:
Debug
Release
ClientFoo (copied from Release)
ClientBar (copied from Release)
I created a new entry, ClientXYZ (copied from Debug), then right-clicked web.config and chose Add Config Transform. I applied the transform rules, and when previewed, the transforms display correctly.
When I select ClientXYZ in the solution config drop down, and start the debugger...
...I see that the web.config used to initiate the application is the Debug one, and not my new ClientXYZ version.
Is it possible to run the project locally with web.config transforms applied, for debugging?
Web config transforms are only applied during publishing or building deployment packages by default (it does, after all, overwrite web.config). There is a way with some adjustments, however, described in this answer: https://stackoverflow.com/a/35561167/1464084
The purpose of using "Debug" and "Release" in Visual Studio are:
Debug constant defined in Debug configuration when you are developing application
Release optimize code enabled in Release configuration when you host that application for client side testing or publishing
Custom (ClientXYZ) constant defined for a developer's own settings (localhost or different IP's) for both Client site hosting and publishing your site

How to tackle machine-dependant configuration with SVN and VS2010?

To start with some background, I am a member of a small team developing an ASP.NET application. In addition to us, there are 2 other teams working on it, all from different countries. Source code is hosted on a shared SVN server but there is no central testing environment. Each developer runs the app on their own machine and data services are set up per team.
Unfortunately our SVN workflow has some gaps in it: annoyances arise when there is time for an SVN update.
It is mainly because each developer and team have slightly different environments in terms of disk directory structure and configuration (both IIS and app itself). Hence conflicts in configuration files and elsewhere that in essence are not conflicts at all - for runtime configuration (XML) and in *.suo.
How should we handle this if our objective is to keep checkout, app setup and update as painless as possible?
One option would obviously be master copies. Another one establishing uniformity in developer environments and keeping it. But what about a third alternative?
One thing to do is to not put the .suo files into SVN, there's no reason to do that.
For IIS configuration there should be no argument - uniform environment across the build team.
For app.config files and the like, I tend to keep them in a separate "cfg" directory in the root of the project and use pre-build events to copy in the relevant ones I need depending on the project and environment I'm working on.
You could have a separate build task to copy in user-specific config into your output directory. Add a new directory in your root project called "user.config or something, and leave it empty. Then configure your project build to check this for entries and copy them to the output directory. This is easy to do, and then each dev can have their own config without affecting the master copies. Just make sure you have an ignore pattern on that folder so you don't commit user-specific configuration. If you have svnadmin access to your source code repo, you could set a hook to prevent it from ever happening.
Also set ignore patterns on your root directory (recursively) for .suo, .user, _Resharper or any other extensions you think are pertinent. There are some So questions already on exactly this topic:
Best general SVN Ignore Pattern?
Ignore *.suo and *.user files in svn. It is easy. After that create two types of config files in subversion. Development and Server, if in use add Test also. See below example.
ConnectionStringDevelopment.config
ConnectionStringServer.config
AppSettingsDevelopment.config
AppSettingsServer.config
Server files would contain server information. Development files is not contained in svn and ignored there. Every new developer will start by copying server files and making changes according to his environment.
Look following example site
http://code.google.com/p/karkas/source/browse/trunk/Karkas.Ornek/WebSite/web.config
following lines are interest.
<appSettings configSource="appSettingsDevelopment.config"/>
<connectionStrings configSource="ConnectionStringsDevelopment.config" />
ConfigSource can be used almost everywhere in web.config therefore you will be able to change every config to every developer. Only make use of following naming convention. ignore *Development.config in subversion. This way no developer config will be added to subversion.
Its not a perfect solution (and should only be used if there are not many of those special files), but what I do is to add fake files for each case, and switch the real file locally to it.
In detail: I have a file foo that creates the problem. I also create foo_1 and foo_2 and then locally switch foo to foo_1 (I use tortoisesvn, so I cant really give you the command line to do that). Then I am working on foo on my machine, but actually commit to foo_1. Other parties could then switch to foo_2...
(I admit this is basically a variant of the master-file approach you suggested yourself; but if there are not many actual changes to those files this at least reduces the numer of conflicts you have to think about)

Can web.config transforms be chained?

Let's pretend that we have the following servers [dev, test, production] and that dev and test are very similar in configuration while production is quite different.
If I'm using web.config transforms that means I have to duplicate a lot of settings för Web.dev.config and Web.test.config. It would be very nice if I could use the same transform mechanism for my transforms so that test.config is based on dev.config.
I have thought of two possible approaches, i'm not sure any of them would work:
Try to get MSBuild to first transform dev.config and then run test.config against the result when we are running under test configuration
trying to get the transform mechanism to work for transformations files. I would somehow run test.config against dev.config and create a temporary file which I then use as as a transformation against Web.config.
Does anyone know if something like this is possible? And if so how would one go about to set it up?
The TransformXml is just an MSBUILD task that is invoked post compile. If you extend/mod your build you can have it run the transform task twice, or allow the normal run against your configurations, then provide a second file and use the task to perform that.
If you are familiar with msbuild, this is pretty simple. If not, reply/comment, and I'll try to provide examples later today.
But in the end, yes its possible, as I've had similar need on past projects.
I have even more configurations. And all of them synced with T4. See my answer here.
Although this has been answered I wanted to update it with an answer reflecting changes made in Visual Studio 2012 that make this considerably easier.
As of Visual Studio 2012 it is possible to "chain" build and publish profile transforms.
As such you can have a "Release" build transform that takes care of common configuration such as switching off debugging, switching on custom errors, and any number of "Publish" transforms which are associated with a publish profile, adding instance specific data such as connection strings and appSettings.
In VS 2012 (as well as the publishing updates for VS2010 through the
Azure SDK) now support the concept of publish specific transforms. You
can also now specify the project configuration used for a profile when
publishing on the publish dialog...
In this case I have created a profile named Production and set the
Configuration to Release. When I publish this project the following
transformations will be applied (if the files exist) in this order.
1.web.release.config
2.web.production.config
See Profile specific web.config transforms and transform preview for more information.

Visual Studio 2010 can apply Debug or Release transformations to Web.config, but what about the Azure settings?

Do I have to manually edit the Azure connection strings myself to switch between production and development, or is there something comparable to the Transformation Visual Studio applies to Web.Config?
To add to what Brent has said. I use a special small configuration-only (Config) project that contains a folder for every deployment type - inside each folder there is a collection of .config and .cscfg files that are tailored toward a specific deployment (a few partial .config files too). During every compile via Pre-Build event step, Visual Studio copies the files from the correct folder into the root folder of that Config project.
This is the command I use in the Pre-Build Event Command Line:
xcopy /Y "$(ProjectDir)$(ConfigurationName)\*.config" "$(ProjectDir)"
xcopy /Y "$(ProjectDir)$(ConfigurationName)\*.cscfg" "$(ProjectDir)"
Every other project in the solution links to the configuration files from the root folder of the Config project.
I also use config transformations as well, for Production vs. Non-production environments. Everything non-Production (local development environment, Azure-QA development environment) has a lot of debug and tracing built in - errors are returned completely to the clients/etc. Production environment has that locked down.
Edit: wrote a blog about this finally: http://www.paraleap.com/blog/post/Managing-environments-in-a-distributed-Azure-or-other-cloud-based-NET-solution.aspx
As Brent pointed out, it is not a good idea to have Staging area to be a full-blown Testing site. It is more geared toward a quick smoke test as well as a great way to deploy a new package into Azure without taking your main site down. (IP swap between Production and Deployment usually does not cause any issues to users)
Hope this helps
First a question, are you referring to configuration settings in the traditional configs? Or in the cloud service config (cscfg)?
If the later, then ATM I'm not aware of any support for configuration transformation. The approach I've seen most folks taking is to maintain number configuration files and use the appropriate file when doing your azure deployment.
This subject also touches on usage of the "Staging" environment. I've seen some folks using it as a parallel testing environment. In practice, its more affective to use it as a staging area to smoke test a new deployment before rolling it into production. If you have a need for a longer term test environment, I've found it better to deploy those services to their own unique namespaces that are then sandboxed away from the production services.
This again touches on ALM best practices for Azure (versioning, deployments, etc..). Something I believe the PNP team is working on and will hopefully have recommendations for soon.
Like knightpfhor said, you can use Visual Studio config transformations if you edit the .ccproj file manually. My answer to a similar question lists the minimum number of steps required to get transformations working.
You can use CloudConfigurationManager in Azure SDK 1.7 http://msdn.microsoft.com/en-us/LIBRARY/microsoft.windowsazure.cloudconfigurationmanager
This starts by looking in the ServiceConfiguration.cscfg e.g. ServiceConfiguration.Cloud.cscfg for config setting. If it isn't there it falls back to web.config and app.config
For example
CloudConfigurationManager.GetSetting("StorageConnectionString")
Will look in the appropriate cscfgfile for StorageConnectionString setting, then it will search the web.config and then app.config.
The simple answer to your question is yes, but you have to mess around with the .ccproj file manually to do it. A full description on how to to do this can be found here

Dynamically setting the IISUrl of a Web Application Project

I have a web application project that I'd like to be able to branch and develop on a totally separate IIS site and not have to keep editing the vbproj IISUrl setting each time I do it. I have tried adding an import of some standard properties so I can maintain them outside of the WAP file but when I reference them in the element it doesn't like them. I suspect it's because the IISUrl element is part of which is a place to put non msbuild info.
As you can see in the code below, I'm trying to reference $(CustomUrl) in a couple spots in the WebApp1.vbproj but when I open VS it's not liking it.
Any way to resolve this or does anyone have a better way to branch off Web Application projects.
CustomImport.vbproj
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CustomUrl>http://localhost/WebUrl_1</CustomUrl>
</PropertyGroup>
</Project>
WebApp1.vbproj
<Import Project="CustomImport.vbproj"/>
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>1124</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>$(CustomUrl)</IISUrl>
<OverrideIISAppRootUrl>True</OverrideIISAppRootUrl>
<IISAppRootUrl>$(CustomUrl)/</IISAppRootUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>$(CustomUrl)</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
I believe I might have a workaround for this in VS2010.
Right click on the project in VS2010 and go to Properties. In the Web tab, Uncheck the "Apply server settings to all users (store in project file)". What this does is forces all of the settings to be stored in a [Web Project Name].csproj.user file instead of in the project file itself. (Mine is a C# project instead of VB, but I assume it works the same) This allows you to have different server settings on each machine doing development, but at the same time share the rest of the configuration.
I had to do this because I'm using SSL certificates on each development machine (workstation and laptop) so the Project URL is different, but I don't want to have to manually mess with the URL on each machine more than once and worry about it while checking my code into source control.
Once you've done the initial configuration on a machine after getting the latest source, your .user file holds the configuration. So long as you're not checking .user files into source control this seems to work fine.
I've been plagued by the same problem for several years now. The problem persists all the way from Visual Studio .NET (2003) up until now (VS 2010). I have searched for an automated solution for automatic URL renaming but without any success.
What I've been doing to avoid this problem is branching way more and having lots of different workspaces:
Root branch for ongoing project
-> Branch for dev-team
-> Branch for support and long-term code integrity (this is the most commonly used branch by me)
-> My personal custom branches that have different URLs set
I know it's not the best solution but this is the best one that I could figure out.
This article on programmatically changing a project file may be of some use to you in creating a solution to automate the changing of those settings:
Programmatically change Web project settings from dynamic port to static

Resources