In this post we will look at how to write a piece of code that will allow your Application to be Environment aware and change where it receives it’s connection string when hosted on Windows Azure.
Are you looking to get started with Windows Azure? If so, you may want to read the post “Get your very own Cloud Playground” to find out about a special offer on Windows Azure Deployments.
State of Configuration
In a typical ASP.NET application the obvious location to store a connectionString is the Web.config file. However when you deploy to Windows Azure the web.config gets packed within the cspkg File and is unavailable for configuration changes without redeploying your application.
Windows Azure does supply an accessible configuration file to store configuration settings such as a connectionString. This file is the cscfg file and is required to upload a Service to Windows Azure. The cscfg file is definitely where you will want to place the majority of your configuration settings that need to be modified over the lifetime of your application.
I know you’re probably asking yourself, what if I want to architect my application to work both On-Premise and in the Cloud on one Codebase? Surprisingly, this is possible and I will focus on a technique to allow a Cloud focused application to be deployed on a Shared Hosting or On-Premise Server without the need to make a number of Code Changes.
Obviously this solution does fit within a limited scope, and you may also want to consider architecting your solution for cost as well as portability. When building a solution on Windows Azure, look into leveraging the Storage Services as part of a more cost effective solution.
Cloud Aware Database Connection String
One of the most common Configuration Settings you would like to be “Cloud-Aware” is your Database Connection String. This is easily accomplished in your application code by making a class that can resolve your connection string based on where the code is Deployed.
How do we know where the code is deployed you ask? That’s rather simple, Windows Azure Provides a static RoleEnvironment Class which exposes a Property IsAvailable which only returns true if the Application is running in either Windows Azure itself or the Windows Azure Compute Emulator.
Here is a code snippet that will give you a rather good idea:
namespace Net.SyntaxC4.Demos.WindowsAzure
{
using System.Configuration;
using Microsoft.WindowsAzure.ServiceRuntime;
public static class ConnectionStringResolver
{
private static string connectionString;
public static string DatabaseConnectionString
{
get
{
if (string.IsNullOrWhiteSpace(connectionString))
{
connectionString = (RoleEnvironment.IsAvailable)
? RoleEnvironment.GetConfigurationSettingValue("ApplicationData")
: ConfigurationManager.ConnectionStrings["ApplicationData"].ConnectionString;
}
return connectionString;
}
}
}
}
Let’s take a moment to step through this code to get a better understanding of what the class is doing.
As you can see the class is declared as static and exposes one static property, this property will either grab the Configuration Setting that is required for the particular environment the Application is Deployed on.
If the connectionString variable has not been previously set a conditional statement is evaluated on the RoleEnvironment.IsAvailable Property. If the condition is found to be true the value of connectionString is retrieve from the CSCFG file by calling a static method of the RoleEnvironment class GetConfigurationSettingValue this searches through the Cloud Service Configuration file for a Value on a Setting with the Name “ApplicationData”.
If the RoleEnvironment.IsAvaliable Property evaluates false, the application is not hosted in the Cloud and the ConnectionString will be collected from the web.config file by using the System.Configuration.ConfigurationManager class.
The same technique can be used to resolve AppSettings by accessing the AppSettings NameValueCollection from the ConfigurationManager class.
Beyond The Basics
There are a few other things you may come across when creating your Cloud Aware application.
Providers, Providers, Providers
ASP.NET also contains a powerful Provider model which is responsible for such things as Membership (Users, Roles, Profiles). Typically these settings are configured using string look-ups that are done within the web.config file. This is problematic because we don’t have the ability to change the web.config without a redeployment of our Application.
It is possible to use the RoleEntryPoint OnStart method to execute some code to programmatically re-configure the Web.config, but that can be both a lengthy process as well as a very error prone way to set your configuration settings.
To handle these scenarios you will want to create a custom provider and provide a few [well documented] configuration settings within your Cloud Service Configuration file that are used by Convention.
One thing to note when using providers is you are able to register multiple providers, however you can only provide so much information in the web.config file. In order to make your application cloud aware you will need to wrap the use of the provider objects in your code with a check for RoleEnvironment.IsAvailable so you can substitute the proper provider for the current deployment.
Something to Consider
Up until now we’ve been trying to [or more accurately managed to] avoid the need to recompile our project to deploy to the Cloud. It is possible to package your Application into a Cloud Service Package without the need to recompile, however if you’re building your solution in Visual Studio there is a good chance the Application will get re-compiled before it is Packaged for a Cloud Deployment.
With this knowledge under your belt it enables a unique opportunity for you to remove a large amount of conditional logic that needs to be executed at runtime by handing that logic off to the compiler.
Preprocessor Directives are a handy feature that don’t get leveraged very often but are a very useful tool. You can create a Cloud Deployment Build Configuration which supplies a “Cloud” Compilation Symbol. Leveraging Preprocessor Conditional logic with this Compilation Symbol to wrap your logic that switches configuration values, or Providers in your application can reduce the amount of code that is executed when serving the application to a user as only the appropriate code will be compiled to the DLL. To Learn more about Preprocessor Directives see the first Programming Article I had written.
Conclusion
With a little bit of planning and understanding the application you are going to be building some decisions can be made really early to plan for an eventual cloud deployment of an application without the need for an abundance of code being written during the regular development cycle nor is there a need to re-write a large portion of your application if you would like to build the functionality in once the Application is ready for Cloud Deployment. With this said there are still obvious improvements to be gained by leveraging the Cloud Platform to it’s full Potential. Windows Azure has a solid SDK which is constantly and consistently iterated on to provide developers with a rich development API.
If you want to leverage more of Windows Azure’s offerings it is a good idea to create a wrapper around Microsoft’s SDK so you will be able to create a pluggable architecture for your application to allow for maximum portability from On-Premise to the Cloud and ultimately between different cloud providers.
Happy Clouding!
This article also appears on SyntaxC4's Blog.