PAGES

22

Jun 12

Smarter Settings in June 2012 Azure SDK



Looking over the features in the newest Azure SDK, I was interested in the new CloudConfigurationManager class and its GetSettings method.  It looked like it was smarter than the RoleEnvironment.GetConfigurationSettingValue method.  Here’s why I think something as  mundane as settings method could be interesting:

Azure opens up some new features to take advantage of in your application like table and queue storage, but ideally, building applications that live in Azure shouldn’t slow down your progress or introduce new pain for features and procedures you’ve been used to.  For example, when building an MVC site, using the Azure compute and storage emulators is going to be necessary at some point especially when I need to test some Azure features before deploying.  But for some of my development, I should also be able to debug my site locally just like I would using the Visual Studio dev web server (“Cassini”) – it’s way faster than deploying to the emulator for every change.  And the code I’m testing is likely to involve (you guessed it) settings.

So like many people out there, I think it makes sense to abstract getting settings through some layer like a SettingsManager class that knows whether to get settings from Azure config because I’m running in the cloud (or emulator) or just get from my appSettings because I’m running locally.  I wanted to see if this is what the new method is doing so I compared a few combinations of settings and method calls in some sample class called SettingsManager.

The out of the box RoleEnvironment.GetConfigurationSettingValue method will throw an Exception if you’re debugging locally which makes sense because you’re not running in a Role – but that inhibits your development workflow.  You can see one way of overcoming this with the previous SDK in the GetSettingTheOldSmarterWay method of the following example SettingsManager code.  That’s the general approach we went with on a previous project.

/// <summary>
/// Wrapper to abstract getting settings.  Beyond what it is showing here, it can
/// allow you to do things like pass in default values and decrypt settings if you choose to.
/// </summary>
public class SettingsManager
{
    /// <summary>
    /// Out of the box, you'll get an exception if not running in Azure and it won't check your appSettings
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string GetSettingTheOldOOBWay(string key)
    {
        string configValue = null;
        configValue = RoleEnvironment.GetConfigurationSettingValue(key);
        return configValue;
    }

    /// <summary>
    /// Making it smarter, you can eat the exception if the setting isn't there, and then check
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string GetSettingTheOldSmarterWay(string key)
    {
        string configValue = null;
        if (RoleEnvironment.IsAvailable)
        {
            try
            {
                configValue = RoleEnvironment.GetConfigurationSettingValue(key);
            }
            catch
            {
                // eat - setting must not be there
            }
        }
        else
        {
            configValue = ConfigurationManager.AppSettings[key];
        }

        return configValue;
    }

The new CloudConfigurationManager code as seen below does this for you now.  It also is doing one more thing.  If the setting your looking for is not in your Azure config while you’re running in Azure, it will check your appSettings.  That would be easy enough to add above if you are on the older SDK, too, but I think you have to think about whether you are just trying to satisfy the development process, or if you want the appSettings to act like a default or backup.  I’m not saying one is right or wrong, I just wanted to share how these work to help you decide and know what you’re doing.

    /// <summary>
    /// Getting the new way is the same as GetSettingTheOldSmarterWay but also will also check appSettings when running in Azure if Azure config is missing the setting.
    ///
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string GetSettingTheNewWay(string key)
    {
        string configValue = null;
        configValue = CloudConfigurationManager.GetSetting(key);
        return configValue;
    }

Here are examples of this in action using this very simple MVC Controller and View.

HomeController.cs

public class HomeController : Controller
{
    private const string TEST_SETTING_KEY = "MvcWebRole1.Controllers.HomeController.TestSetting";

    public ActionResult Index()
    {
        try
        {
            ViewBag.SettingTheOldOOBWay = SettingsManager.GetSettingTheOldOOBWay(TEST_SETTING_KEY);
        }
        catch
        {
            // eat exception
        }
        ViewBag.SettingTheOldSmarterWay = SettingsManager.GetSettingTheOldSmarterWay(TEST_SETTING_KEY);
        ViewBag.SettingTheNewWay = SettingsManager.GetSettingTheNewWay(TEST_SETTING_KEY);

        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

Index.cshtml

@{
    ViewBag.Title = "Home Page";
}

<h3>Setting The Old Out of the Box Way</h3> @ViewBag.SettingTheOldOOBWay

<h3>Setting The Old Smarter Way</h3> @ViewBag.SettingTheOldSmarterWay

<h3>Setting The New Way</h3> @ViewBag.SettingTheNewWay

Debugging locally you get this:

Debugging Locally

Debugging in Azure with the setting in the Azure config file you see this:

Debugging in Azure with settings in Azure Config

And lastly, debugging in Azure without setting in the Azure config you see this:

Debugging in Azure without setting in Azure Config

Lastly, I will say that even with the new code, I think you should wrap your settings in a class like the SettingsManager above.  It gives you the ability to pass in defaults from code, decrypt in a consistent way and do other fun things you can think of in a discoverable and expected way.  Also be warned that it looks like the new code tries to log if your key isn’t there so don’t have ensure the Azure trace listener in your config is not enabled because it will throw an exception and you’re back to where you were at the beginning.

  <system.diagnostics>
    <trace>
      <listeners>
        <!--keep Azure Trace Listener commented out when not running in Azure to avoid exceptions-->
        <!--<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics">
          <filter type="" />
        </add>-->
      </listeners>
    </trace>
  </system.diagnostics>

UPDATE: It dawned on me after watching a TechEd 2012 video by Nick Harris that the other reason this new API exists is to have code that can work independent of whether you’re accessing a setting in a WebRole which has Azure settings or a WebSite which will only have the web.config.

Comments Off , permalink


Tagged , ,

Comments are closed.