Yes, you can do this - and it is even very easy once you know how.
App.config is not transformed by design but fortunately the Azure Team made the build/deploy process very extensible exactly for these kinds of scenarios. What you need to do is reasonably well documented, though in a very roundabout way and most articles assume you are already familiar with MSBuild scripts and the like.
Below you will find the lines you need to put into your project that will make this Just Work. That should take no more than five minutes. Please note that this is not a hack - the whole Azure deploy process is designed to support this kind of thing.
If you want to know more, there are some links to related articles at the bottom.
Some conceptual points
- The recommended way to achieve this kind of thing in Azure is to not use Web.config and App.config but instead use the CloudConfigurationManager and use Role Settings. However, sometimes that just isn't the right answer, usually because of built-in or 3rd party components that require *.config settings (smtp, wcf, elmah etc).
- Web Config transformations is designed for transforming only the web.config. This means that app.config is not transformed by design.
- Web Config transformations is designed to only kick in when publishing so when you run locally, even in the Cloud Emulator, your Web.config won't be transformed.
The way we can solve this is by hooking into the build process for the Cloud project. When you deploy the project to Azure, the Cloud project will be built using a build process you can hook into. In short, the cloud project builds the web and worker roles and puts them under the Obj folder under your cloud project. It then runs a process that essentially zips all that up and finally put the result into the Bin folder. From there, the "zip" file and a configuration file is uploaded to Azure.
The solution
Is to manually edit your Cloud.csproj file (if you do it from within Visual Studio you need to unload the project first).
Then add this right above the closing </project>
tag:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.targets" />
<PropertyGroup>
<WorkerRoleDir>$(IntermediateOutputPath)WorkerRole1\</WorkerRoleDir>
<AppConfigOriginal>$(WorkerRoleDir)WorkerRole1.dll.config</AppConfigOriginal>
<AppConfigTransformer>$(SolutionDir)WorkerRole1\App.$(Configuration).config</AppConfigTransformer>
<AppConfigAfterTransformed>$(WorkerRoleDir)AfterTransformed.config</AppConfigAfterTransformed>
</PropertyGroup>
<Target Name="TransformAppConfig" AfterTargets="AfterPackageComputeService">
<Message Text="Transforming $(AppConfigOriginal) via $(AppConfigTransformer) to $(AppConfigAfterTransformed)" />
<TransformXml Source="$(AppConfigOriginal)" Transform="$(AppConfigTransformer)" Destination="$(AppConfigAfterTransformed)" />
<Copy SourceFiles="$(AppConfigOriginal)" DestinationFiles="$(WorkerRoleDir)App.Config.Original" />
<Copy SourceFiles="$(AppConfigAfterTransformed)" DestinationFiles="$(AppConfigOriginal)" />
</Target>
Notes
- There are a couple of hard-coded paths in there that you will have to modify. I am sure there is a way to make them soft but that requires more MSBuild skills than I have.
- The transformation will actually run when you deploy to your local Cloud Emulator, but it won't be used. As such, the result is consistent with the behavior of Web.config which is also not transformed. But, if your transformation was to fail, you will get a build error even when just running in the Emulator.
- See also This other SO question
- An in-depth exploration
- Tom Hollanders highly linked article on deploying directly from MSBuild
.csproj
are NOT enough to make it "just work" for everybody else - something additional is required. I don't know what that something additional is, though. :-( – Jaxidian