This is an ongoing series on Window’s Azure.  The series starts here, and all code is located on GitHub:https://github.com/mmooney/MMDB.AzureSample.

Introduction

In the last post, we covered how to easily deploy a Azure Cloud Service using the new Sriracha 2.0 command line tools, specifically the Deploy Cloud Service Task.

In that post, we just covered the minimum amount of configuration to get a basic Cloud Service site up and running.  In this post, we’ll cover the handful of more advanced configuration options that will hopefully make you’re live easier.

In the last post, we had a pretty basic configuration file:

{
    "AzureSubscriptionIdentifier": "ThisIsYourAzureSubscriptionIdentifier",
    "AzureManagementCertificate" : "ThisIsYourAzureManagementCertificate",
    "ServiceName" : "AzureViaSriracha",
    "StorageAccountName" : "srirachademo",
    "AzurePackagePath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\MMDB.AzureSample.Web.Azure.cspkg",
    "AzureConfigPath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\ServiceConfiguration.Cloud.cscfg"
}

 

For this post, we’re doing to add a bit more configuration to our project:

{
    "AzureSubscriptionIdentifier": "ThisIsYourAzureSubscriptionIdentifier",
    "AzureManagementCertificate" : "ThisIsYourAzureManagementCertificate",
    "ServiceName" : "AzureViaSriracha",
    "StorageAccountName" : "srirachademo",
    "AzurePackagePath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\MMDB.AzureSample.Web.Azure.cspkg",
    "AzureConfigPath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\ServiceConfiguration.Cloud.cscfg"
    "RoleList": {
        "MMDB.AzureSample.Web": {
            "InstanceCount": 2,
            "ConfigurationSettingValues": {
                "TestSettingValue1": "Vote Quimby",
                "TestSettingValue2": "He'd vote for you"
            },
            "CertificateThumbprints": {
                "MySSLCert": "ThisIsYourSSLThumbprint"
            }            
        }
    }
}

In this case, we’re not just setting the core configuration for the Azure Cloud Service package itself, but also some configuration for the Web Roles and/or Worker Roles contained in that package, along with the SSL certificate information.

AppSettings vs. Azure ConfigurationSettings

In most non-Azure ASP.NET web applications, you would specify most of your configuration in the appSettings or connectionStrings elements.  For example, you might have something like this in your web.config:

<appSettings>
  <add key="TestSettingValue1" value="This is the first test value"/>
  <add key="TestSettingValue2" value="This is the second test value"/>
</appSettings>

 

And then this in your ASP.NET MVC controller (using the handy AppSettingsHelper from the MMDB.Shared library, available on NuGet):

public ActionResult Index()
{
    var model = new SettingsViewModel
    {
        TestSettingValue1 = AppSettingsHelper.GetSetting("TestSettingValue1"),
        TestSettingValue2 = AppSettingsHelper.GetSetting("TestSettingValue2")
    };
    return View(model);
}

 

And this in your Razor view:

<p>TestSettingValue1: @Model.TestSettingValue1</p>
<p>TestSettingValue2: @Model.TestSettingValue2</p>

 

Which ends up looking like this:

image

While this sort of works in Azure, your web.config gets bundled up inside the Azure package file, so it can’t easily be changed when you promote it from one environment to another.  Instead, when you deploy your Azure package to a given environment, you also include a configuration file specific to that environment.

So forgetting the web.config for now, but your Azure configuration file might look like this:

<ServiceConfiguration serviceName="MMDB.AzureSample.Web.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*" schemaVersion="2014-01.2.3">
  <Role name="MMDB.AzureSample.Web">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="TestSettingValue1" value="Vote Quimby" />
      <Setting name="TestSettingValue2" value="He'd vote for you" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="MySSLCert" thumbprint="61475037B69532AA6EE96936DF9CBC463A5F5FE8" thumbprintAlgorithm="sha1" />
    </Certificates>
  </Role>
</ServiceConfiguration>

Now you’re ASP.NET MVC controller might look like this:

var settingsAdapter = new MMDB.Azure.Settings.AppSettingsAdapter();
var model = new SettingsViewModel
{
    TestSettingValue1 = settingsAdapter.GetSetting("TestSettingValue1"),
    TestSettingValue2 = settingsAdapter.GetSetting("TestSettingValue2")
};
return View(model);

 

And that pulls the settings from the Azure configuration file instead:

image

Note: This code using our MMDB Azure Settings library, also available on NuGet.  This library will check to see if you’re actually running in an Azure environment (or even the local Azure emulator), and if so will try to pull the values from the Azure configuration file, and then will fall back and check the web.config appSettings if it’s not found there.  Alternatively, it will detect if you’re not running in Azure (either in IIS or just debugging with IIS Express in Visual Studio), in which case it will skip the Azure components and just check the web.config.  This has been invaluable for us to be able to get our whole application working fast locally as a normal ASP.NET website, but then giving us the flexibility to include an Azure configuration file when we deploy to production without having to change any code.

Configuring Azure

Now, this all seems simple enough right?  You may already have some build or deploy scripts that are doing some sort of XML poke to inject values into your web.config at a given XPath, so why can’t you just do the same thing for the Azure file?

Or, to ask another question with the same answer, what is a major reason people hate XML and have been fleeing to JSON?

The answer is XML namespaces.  If you try to write a simple XPath to inject a ConfigurationSetting value, you might try the following:

/ServiceConfiguration/Role[@name="MMDB.AzureSample.Web"]/ConfigurationSettings/Setting[@name="TestSettingValue1"]/@value

And then you would probably be confused why it didn’t find any nodes.

The reason is this xmlns attribute at the top of the configuration file:

<ServiceConfiguration serviceName="MMDB.AzureSample.Web.Azure" 
    xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" 
    osFamily="2" osVersion="*" schemaVersion="2014-01.2.3">

That defines the default namespace to be http://schemas.microsoft.com/blah/blah/blah, and therefore that namespace must be provided at each element when you’re executing an XPath.  Sure, there are ways to simplify this in .NET code, like defining a prefix upfront for the namespace and putting that in a NamespaceManager and passing the NamespaceManager through to the SelectNodes call and …zzzzz…

I’m sorry, you seem to have dozed off.  What I was getting at is that this is annoying and wasteful and let’s not do it that way.

Sriracha’s Deploy Azure Cloud Service Task to the rescue

As we mentioned in the last post and above, you can use the Sriracha command line deployment tools to easily push an Azure package to up to the cloud.

And since the poking configuration values into Azure configuration files can be painful, we made sure to simplify this process as well.

So if we use the following configuration file to call the Sriracha Azure Deploy Cloud Service Task, it will automatically inject the values into the our Azure configuration file during the deployment:

{
    "AzureSubscriptionIdentifier": "ThisIsYourAzureSubscriptionIdentifier",
    "AzureManagementCertificate" : "ThisIsYourAzureManagementCertificate",
    "ServiceName" : "AzureViaSriracha",
    "StorageAccountName" : "srirachademo",
    "AzurePackagePath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\MMDB.AzureSample.Web.Azure.cspkg",
    "AzureConfigPath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\ServiceConfiguration.Cloud.cscfg"
    "RoleList": {
        "MMDB.AzureSample.Web": {
            "InstanceCount": 2,
            "ConfigurationSettingValues": {
                "TestSettingValue1": "Vote Quimby",
                "TestSettingValue2": "He'd vote for you"
            },
            "CertificateThumbprints": {
                "MySSLCert": "ThisIsYourSSLThumbprint"
            }            
        }
    }
}

 

The RoleList should match the list of roles in your package, although everything in it is optional so you only have to include the values for the roles you’d like to configure.

Them, you can control the number of instances, the the ConfigurationSettings, and even add the SSL certificate thumbprint if you’re Azure site is configured for using SSL. 

Also, until normal XPath poke approaches, it won’t just replace the configuration elements in your Azure configuration file if they are found, it will add any missing elements as well.

One thing you CAN’T control is the VM size.  For some reason, that is buried in the Azure service definition file, which then buried inside your Azure package.  So if you want to run ExtraSmall instances in your test site but Large instances in production site, you’d have to edit that service definition file before you build the Azure package.  We are also considering a nice-to-have feature during the deployment to crack open the Azure package and update the the VM size value, but is much more involved and some consider it a little scary to be modifying the internals of your packages between environments; but anyone who wants to jump in and submit a pull request for that, it would be greatly appreciated.

Anyhow, that gives you an overview of the how and why, but there is a lot more info on the Sriracha2 wiki: https://github.com/mmooney/Sriracha2/wiki/Azure—Deploy-Cloud-Service-Task

This is an ongoing series on Window’s Azure.  The series starts here, and all code is located on GitHub: https://github.com/mmooney/MMDB.AzureSample.

So in some previous posts we covered how to deploy Azure Cloud Services via Powershell and also via C# code using the MMDB.Azure.Management library.

Now, we’ll cover a quick and easy way to configure and push Azure Cloud Service projects with a single command and configuration file.

Sriracha v2.0

First, to give you some context, we been rebuilding large parts of our Sriracha Deployment System to make it more modular, so you can more easily leverage individual pieces without having to install the whole system.  It’s still very much a work in progress, but our goal is to steady release chunks of useful functionality as they become available.

One things I’ve needed for a while is a quick command line interface to deploy whatever I want whenever I want.  Sure, the traditional Sriracha/Octopus/BuildMaster model is great for scenarios when I can set up a server to catalog out releases, but sometimes you just need a script to push something somewhere and you want it to be as simple as possible.

There is a major design change in the new Sriracha system.  Previously, you couldn’t use anything in Sriracha unless you installed the whole system, but there was a lot of great functionality trapped in there.  This time around, we are building each type of deployment task as standalone libraries that can be executed through a simple command line tool first, and then the broader Sriracha system will then leverage these standalone libraries.

Deploying To Azure In 3 Steps

First, you’ll need an Management Certificate for your Azure account to be able to connect through their REST APIs.  If you don’t have that yet, check out the Authentication section of the last Azure post for steps to get your Subscription Identifier and Management Certificate values from the Azure publish settings.

The idea is pretty simple:

  • We’ll download a command line tool into our solution from Nuget
  • We’ll update a configuration file with the info specific to our project
  • We’ll run the command line tool to execute the deployment.

For this demonstration, we’ll be using the MMDB.AzureSample project we’ve used in earlier Azure posts.   Feel free to pull down the code if you’d like to follow along.

Now we have our solution open, the first thing we’ll do is pull down the Sriracha.DeployTask.Azure package from NuGet. 

PM> Install-Package Sriracha.DeployTask.Azure

 

This will create a SrirachaTools\Runners\Azure directory under your solution.  In there will be sriracha.runner.exe, along with a bunch of DLLs.

image

You’ll notice of those files is “Sample.DeployCloudService.json”.  Let’s put a copy of that named “MyDeployCloudService.json” and put it in the root of our solution and open it up:

image

image

You’ll see a whole bunch of settings in here.  Some of them are required, but most of them are optional.  We’ll add the bare minimum for now:

{
    "AzureSubscriptionIdentifier": "ThisIsYourAzureSubscriptionIdentifier",
    "AzureManagementCertificate" : "ThisIsYourAzureManagementCertificate",
    "ServiceName" : "AzureViaSriracha",
    "StorageAccountName" : "srirachademo",
    "AzurePackagePath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\MMDB.AzureSample.Web.Azure.cspkg",
    "AzureConfigPath": ".\\MMDB.AzureSample.Web.Azure\\bin\\Release\\app.publish\\ServiceConfiguration.Cloud.cscfg"
}

These values are:

  • AzureSubscriptionIdentifier and AzureManagementCertificate are the credentials you got from the Azure publish settings above.
  • ServiceName is the name of your service in Azure.  If this service does not yet exist, it will be created.  When we’re done, the cloud service will have the url http://[servicename].cloudapp.net/.  Note: as you would guess with the URL, this service name must be unique, not just within your account, but also throughout all of Azure cloud services, so be creative.
  • StorageAccountName is an Azure storage account that we need to to hold the Azure package binary during the deployment.  If this account doesn’t exist, it will be created.  Note: the storage account name must be between 3 and 24 characters, and can only contain lower case letters and numbers.
  • AzurePackagePath is the location of your Azure Cloud Service package (*.cspkg).  This can be created by right-clicking your Cloud Service in Visual Studio and selecting Publish
  • AzureConfigPath is the location of the Azure configuration file (*.cscfg) to deploy with your project, also created when you package your Azure Cloud Service.  By default it will use the values from this file, but those values can be overridden during deployment using the configFile paramater below.  We’ll cover the values in the configFile in the next post.

(Make sure you enter your own Azure Subscription Identifier and Management Certificate)

Then from a command line (or a batch file or NAnt script or whatever floats your boat), run the following:

.\SrirachaTools\Runners\Azure\sriracha.run.exe --taskBinary=Sriracha.DeployTask.Azure.dll --taskName=DeployCloudServiceTask --configFile=.\MyDeployCloudService.json --outputFormat text

 

The breakdown here is:

  • Run the Sriracha command line tool (sriracha.run.exe)
  • Use the taskBinary parameter to tell it which assembly has the deployment task implementation (Sriracha.DeployTask.Azure.dll)
  • Use the taskName parameter to tell it what actual task to use (DeployCloudServiceTask)
  • Use the configFile parameter to tell it where our config file lives (MyDeployCloudService.json)
  • Optionally use the outputFormat parameter tell it what type of output format we want back. Normally you’d want text, but you can use json if are piping it somewhere you want a parseable response.
  • You can find the full documentation of calling the Sriracha deployment runner here: https://github.com/mmooney/Sriracha2/wiki/Deployment-Runner 

 

That’s it.  Just run that command, and then sit back and watch the bits fly:

image

 

Now let’s go check out out the site, which again will be at http://[servicename].cloudapp.net, and there we go:

image

Now there are also some other cool things you can do with configuring your cloud service settings, instance counts, and certificates, which we will cover in the next post.

I have been very critical of distributed version control systems (DVCS) in the past.  And like many things I thought in the past, I got older and wiser and now think I was wrong before.  A few years ago I started using Mercurial and Git for some projects, and Git is pretty much a requirement if you want to work with open source code these days, especially on GitHub.  These days, I only go back to using TFS or SVN if it’s a requirement for a certain customer (which it is surprisingly often).

However, getting started with a DVCS it is definitely a conceptual leap from what a lot of .NET developers are working with, since most of them are coming from a TFS/SourceSafe background, or maybe SVN.  Once people make that leap, it the new approach makes a lot of sense, but I know from experience it can be really hard to make that leap when you’ve been used to one approach for most of your career.

Anyhow, while ramping up a developer for a client project that uses Mercurial, I found myself writing this quick conceptual explanation for the twentieth time, so I figured I’d put it here so I can just point to it in the future.  Nothing new here, just my quick explanation.

DVCS Summary

Git and Mercurial are both distributed version control systems.  This is a very different approach from TFS/VSS or even SVN (although SVN is closer).  The core idea is that there is no single centralized server that you need to stay connective to. The repository you have on your own machine is a full blown Mercurial/Git repository, with a full history of the whole project, and you can commit, branch, merge, etc as much as you want with your local repository.  Then when you are ready to release your changes into the wild (what you would normally consider checking into the central server in TFS or VSS), you pull the latest changes from the central repository (like GitHub or BitBucket), do any merging you need to do locally, and then push your changes up to the central server.

This may sound like basically the same thing as SVN but with an extra step (commit locally and then push to the central server, rather than just commiting straight to the central server), but it has its benefits.  Normally if you are working against a central TFS/SVN server, you need to make sure you’re changes are solid and ready for release before checking anything in; before that point you changes are in limbo on your machine, either not checked in for several days (yikes), or you have to shelve them, which can be a pain if your source control platform even supports it.  But in an DVCS, you can work on a feature, or several features locally, committing repeatedly as you go small incremental checkins, without having to worry about breaking anything for anyone else yet. Also, you can make local branches, so you can create a local branch to start working on a big feature that will take several days, but then when a production bug comes in you can switch back to the master/trunk/default branch quickly to fix it and release that fix, without disturbing your feature branch.  While you can make these types of branches in TFS/SVN, they are always done on the server, which gets messy and complicated when you have a lot of developers.  The DVCS approach lets you use work with all of your own mess locally, without having to clutter up anyone else’s workspace, or anyone cluttering yours.  Then you can merge your feature changes into the trunk when it’s actually ready, or better yet before experimental features that never pan out, you can just throw that branch out and go back to the main trunk code.

 

If you want some deeper theory, Eric Sink of SourceGear/Vault fame wrote a great blog series a few years go (coincidentally right before he announced Source Gear was building it’s own DVCS, Veracity:

http://ericsink.com/entries/dvcs_dag_1.html

http://ericsink.com/entries/dvcs_dag_2.html

So your application needs to send emails.  So you start with this:

var message = new MailMessage();
message.From = new MailAddress("donoreply@example.com");
message.To.Add(new MailAddress("jimbob@example.com"));
message.Subject = "Password Reset";
message.Body = "Click here to reset your password: "
                      + "http://example.com/resetpassword?token=" 
                      + resetToken);
smtpClient.Send(message);

 

And that works OK, until you want to send some more detailed, data-driven emails. 

Duh, that’s what StringBuilder is for
var message = new MailMessage();
message.From = new MailAddress("donoreply@example.com");
message.To.Add(new MailAddress("jimbob@example.com"));
message.Subject = "Order Confirmation";

StringBuilder body = new StringBuilder();
body.AppendLine(string.Format("Hello {0} {1},", 
                    customer.FullName));
body.AppendLine();
body.AppendLine(string.Format("Thank you for your order.  "
                    + "Your order number is {0}.", 
                    order.OrderNumber));
body.AppendLine("Your order contained:");
foreach(var item in order.LineItems)
{
    body.AppendLine(string.Format("\t-{0}: {1}x${2:c}=${3:c}",
                    item.ProductName,item.Quanity,
                    item.UnitPrice,item.SubTotal));
}
body.AppendLine(string.Format("Order Total: ${0:c}", 
                    order.OrderTotal));
message.Body = body.ToString();

smtpClient.Send(message);

Yes, this is certainly the wrong way to do it.  It’s not flexible, you have to change code every time the email content changes, and it’s just plan ugly.

On the other hand, much of the time especially (early in a project), this is just fine.  Step 1 is admitting you have a problem, but step 0 is actually having a problem in the first place to admit to.  If this works for you, run with it until it hurts. 

I have a lot of code running this way in production right now, and it works swimmingly, because if there a content change I can code it, build it, and deploy it to production in 15 minutes.  If your build/deploy change is small enough, there is virtually no difference between content changes and code changes.

 

Back to the real problem please

But let’s say you really do want to be more flexible, and you really do need to be able update the email content without rebuilding/redeploying the whole world.

How about a tokenized string?  Something like:

string emailTemplate = "Hello {FirstName} {LastName},"
                       + "\r\n\r\nThank you for your order...";

That could work, and I’ve started down this path many times before, but looping messes you up.  If you needed to include a list of order line items, how would you represent that in a template?

What else?  If you are in 2003, the obvious answer is a to build an XSLT stylesheet. Serialize that data object as XML, jam it into your XSLT processor, and BAM you have nicely formatted HTML email content.  Except writing those stylesheets are a nightmare.  Maintaining them is even worse.  If you don’t have interns that you hate, you’re going to be stuck with it.

So yes of course you could use XSLT.  Or you could just shoot some heroin.  Both will make you feel good very briefly in the beginning, but both will spiral our of control and turn your whole life into a mess.  Honestly, I would not recommend either.

OK, so how about some MVC templatey type things?

The whole templating idea behind XSLT is actually a good idea, it’s just the execution that is painful.  We have an object, we have a view that contains some markup and some presentation-specific logic, we put them all into a view engine blender and get back some silky smooth content.

If you were in ASP.NET MVC web application, you could use the Razor view engine (or WebForms view engine, if you’re into that kinda thing) to run the object through the view engine and get some HTML, but that plumbing is a little tricky.  Also, what if you are not in an MVC web app, or any web app at all?  If you are looking to offload work from your website to background processes, moving all of your email sending to a background Window service is a great start, but it’s tough to extract out and pull in that Razory goodness.

Luckily some nice folks extracted all of that out into a standalone library (https://github.com/Antaris/RazorEngine), so you can execute Razor views against objects in a few limes of code:

string view = "Hello @Model.CustomerFirstName @Model.CustomerLastName, thank you for your order.";
var model = new { CustomerFirstName="Ty", CustomerLastName="Webb" };
var html = RazorEngine.Razor.Parse(view, model);

 

That is awful pretty. But if course we still need to write wrap that up with some SMTP code, so let’s take it a step farther. 

Razor Chocolate + SMTP Peanut Butter = MMDB.RazorEmail

Let’s say I’m lazy.  Let’s say I just want to do this:

new RazorEmailEngine().SendEmail("Order Receipt", model, view, 
                        new List<string>{"jimbob@example.com"}, 
                        "donoreply@example.com");

I couldn’t find anything that was this simple, so built one.  Here it is: https://github.com/mmooney/MMDB.RazorEmail

Just import that into your project via NuGet (https://nuget.org/packages/MMDB.RazorEmail/), and you can start sending emails right away. 

It works in both web apps and and Windows apps (we wrote it specifically because we needed to support this from a Windows Service).

It can use your app.config/web.config, settings or you can pass in different values.  It also has some rudimentary attachment handleing that will need to be improved.

Take a look, try it out, and let me how how it works for you at @mooneydev

Intro

So enums are awesome. They greatly simplify your ability to restrict data fields in clear and self-descriptive way. The C# implementation of enums have alleviated the need for all of those awful “item code”, magic number, and random unenforced constants that can be the source of so many bugs.

However, nothing is perfect, and so there can some rough edges when working with enums. Everyone ends up writing the bunch of plumbing code, or taking shortcuts that are not as type-safe as they could be. MMDB encountered this on several projects at the same time, so we put it all in a helper library (yes, this met our rigid definition of worthwhile reusability). Recently we put this up on github (https://github.com/mmooney/MMDB.Shared) and NuGet (http://nuget.org/packages/MMDB.Shared), so please help yourself.

Is this groundbreaking? Absolutely not. In fact, some may not even consider it all that useful.  But it’s been helpful for us, and it’s one of the first NuGet packages I pull into each new application, so hopefully it can help others simplify some of their code.

Anyhow, let’s get down to it. We’ll run through the problems we encountered with enums, and what we’ve done to solve them.

Parsing Enums

One of the most annoying things with enums is trying to parse random input into a strictly typed enum value. Say you have a string that has come from a database or user input, and you think the value should align nicely. You end up with something like this:

string input = "SomeInputValue";
var enumValue = (EnumCustomerType)Enum.Parse
                 (typeof(EnumCustomerType), inputValue);

 

Ugh. First, you have to pass in the type and cast the result, which is ugly, and should never be necessary since generics were introduced in .NET 2.0. Also, you have to hope that “SomeInputValue” is a valid value for the enum, otherwise you get a wonderful System.ArgumentException, with a  message like “Additional information: Requested value ‘SomeInputValue’ was not found.”, which is moderately helpful.

In .NET 4, we finally got introduced a strictly-typed Enum.TryParse:

string input = "SomeInputValue";
EnumCustomerType enumValue;
if(Enum.TryParse<EnumCustomerType>(input, out enumValue))
{
//...
}

This is much better, but can still be a little clunky.  You have to play the temporary variable game that all .NET TryParse methods require, and if you want to actually throw a meaningful exception you are back to calling Enum.Parse or writing the check logic yourself.

So lets try to simplify this a little with the EnumHelper class in MMDB.Shared.  Our basic Parse is nice and concise:

string input = "SomeInputValue";
var enumValue = EnumHelper.Parse<EnumCustomerType>(input);

And if this is not a valid value, it will throw a exception with the message “Additional information: Unrecognized value for EnumCustomerType: ‘SomeInputValue'”.  I always find a little more helpful to have exceptions tell you exactly what it was trying to do when it failed, not just that it failed.

Also, it has a strictly typed TryParse method, that does not require any temp values.  It returns a nullable enum, with which you can do whatever you like:

string input = "SomeInputValue";
EnumCustomerType? enumValue = 
             EnumHelper.TryParse<EnumCustomerType>(input);
return enumValue.GetValueOrDefault
             (EnumCustomerType.SomeOtherInputValue);

Enum Display Values

The next problem we run into assigning display values to enums, and more importantly easily retrieving them.

OK, so this has been done a few times.  In most cases, people have used the System.ComponentModel.DescriptionAttribute class to assign display values to enums:

public enum EnumCustomerType 
{
    [Description("This is some input value")]
    SomeInputValue,
    [Description("This is some other input value")]
    SomeOtherInputValue
}

Also the MVC folks introduced a DisplayAttribute in System.ComponentModel.DataAnnotations:

public enum EnumCustomerType 
{
	[Display("This is some input value")]
	SomeInputValue,
	[Display("This is some other input value")]
	SomeOtherInputValue
}

So lots of options there, with lots of dependencies.  Anyhow, to keep it minimal, we created a simple class specifically for enum display values:

public enum EnumCustomerType 
{
	[EnumDisplayValue("This is some input value")]
	SomeInputValue,
	[EnumDisplayValue("This is some other input value")]
	SomeOtherInputValue
}

What’s fun about this is that you can now get your display value in a single line:

public enum EnumCustomerType 
{
	[EnumDisplayValue("This is some input value")]
	SomeInputValue,
	[EnumDisplayValue("This is some other input value")]
	SomeOtherInputValue
}
//...
//Returns "This is some input value"
string displayValue = EnumHelper.GetDisplayValue
                       (EnumCustomerType.SomeInputValue);

And if you don’t have an EnumDisplayValue set, it will default to the stringified version of the enum value:

public enum EnumCustomerType 
{
	[EnumDisplayValue("This is some input value")]
	SomeInputValue,
	[EnumDisplayValue("This is some other input value")]
	SomeOtherInputValue,
	SomeThirdValue
}
//...
//Returns "SomeThirdValue"
string displayValue = EnumHelper.GetDisplayValue
                        (EnumCustomerType.SomeThirdValue);

Databind Enums

Next, let’s do something a little more useful with the enums.  Let’s start databinding them.

Normally if you want to display a dropdown or a radio button list or other type of list control to select an enum, you either have to manually create all of the entries (and then make sure they stay in sync with the enum definition), or write a whole bunch of plumbing code to dynamically generate the list of enum values and bind them to the control.  And if you want to include display values for your enums, it’s even worse, because you have to map the enum values and display values into object that exposes those fields to the DataTextField and DataValueField in the  list control.  Meh.

Or, you can just do this:

EnumHelper.DataBind(dropDownList, typeof(EnumCustomerType));

This will retrieve the the enum values, and their display values, put them into a list, and bind it to the control.

I know what you’re going to say.  “But I want to hide the zero enum value because that is really the ‘None’ value”:

EnumHelper.DataBind(comboBox, typeof(EnumCustomerType), 
             EnumHelper.EnumDropdownBindingType.RemoveFirstRecord);

Or, “I want to display the first zero record in my combobox, but I want to clear it out because it’s not a real valid selection, it’s just the default”:

EnumHelper.DataBind(comboBox, typeof(EnumCustomerType), 
             EnumHelper.EnumDropdownBindingType.ClearFirstRecord);

Or even, “yeah I want that blank first record in my combobox, but I don’t have a zero/none value defined in my enum values, so I want to add that when databinding”:

EnumHelper.DataBind(comboBox, typeof(EnumCustomerType), 
             EnumHelper.EnumDropdownBindingType.AddEmptyFirstRecord);

Conclusion

So again, nothing groundbreaking here.  Hey, it may not even be the best way to handle some of this stuff.  But it works great for us, removes a lot of the unnecessary noise from our code, and makes it a lot easier to read our code and get to the intent of what is being down without a whole lot of jibber-jabber about the how.

Hopefully this can make one part of your coding a lot easier.  Any feedback or suggestions welcome, or better yet, submit a patch Smile