enums

Getting All Valid Enum Values in ASP.NET Web API

One of the commenters on my blog posed an interesting question on my article about serializing enumerations in Web API:

A comment on my blog, asking

He wanted to know how someone who is querying a Web API might know what possible values a given enumeration has. I didn't answer that in the post he commented on, so I'll do that now. How do we tell consumers what possible values an enumeration in a Web API app has?

Let's say we have the following enums:

public enum AddressType  
{
    Physical,
    Mailing,
    Shipping
}

public enum AccessLevel  
{
    Administrator,
    ReadWrite,
    ReadOnly
}

We want to expose a query which returns these values for each enumeration. To do that, let's create a class for EnumValue:

public class EnumValue  
{
    public string Name { get; set; }
    public int Value { get; set; }
}

It's a pretty generic class, to be sure, but since all enumerations are is a name and a value it serves our purposes well enough.

The trick now is to create an extension which uses Reflection to get all the names for the given enum. In fact, we can even make that method generic, so it can be used for any enumeration at all.

public static class EnumExtensions  
{
    public static List<EnumValue> GetValues<T>()
    {
        List<EnumValue> values = new List<EnumValue>();
        foreach (var itemType in Enum.GetValues(typeof(T)))
        {
            //For each value of this enumeration, add a new EnumValue instance
            values.Add(new EnumValue()
            {
                Name = Enum.GetName(typeof(T), itemType), 
                Value = (int)itemType
            });
        }
        return values;
    }
}

Finally, we can use Web API methods that call this extension:

public class HomeController : ApiController  
{
    [HttpGet]
    [Route("accesslevels/all")]
    public IHttpActionResult GetAccessLevels()
    {
        return Ok(EnumExtensions.GetValues<AccessLevel>());
    }

    [HttpGet]
    [Route("addresstypes/all")]
    public IHttpActionResult GetAddressTypes()
    {
        return Ok(EnumExtensions.GetValues<AddressType>());
    }
}

When we call this method using Postman, we now get an appropriate response code (200 OK) and the data we were looking for. Here's the address types:

A Postman response, showing the three possible values for the enumeration AddressType

And here's the access levels:

A Postman response, showing the three possible values for the enumeration AccessLevel

Of course, this is just one of many possible solutions to this particular problem. I like this method because it's generic and reusable for all enumerations, but if you find a better method, please feel free to share in the comments!

That's all there is to it! Now any consumer can hit these methods and know exactly what values can be used for the AccessLevel and AddressType enumerations!

I also have a repository over on GitHub which stores the sample code for this post. Check it out!

Happy Coding!

Using T4 Templates to Generate Enums From Database Lookup Tables

The major project we've been working on had a non-unusual requirement: take these SQL database tables and convert them to enumerations we can use over a service. A quick Google search found some code that did exactly what we wanted, so of course we (ok, I) copied-and-pasted that code into our solution and BAM, it worked like a charm.

Problem was, when someone asked me to explain what it did, I couldn't. I can't stand not understanding something, especially not something that enables my projects to work, so I dove into this unfamiliar T4 Templates technology and came out the other side with a little more knowledge than I'd started with. Perhaps it will help you too.

Something Really Clever

As I said earlier, we had a requirement for this big project we're working on to use values from a set of database lookup tables as Enumerations in my server code. Given that I'm already a big fan of using Enums to reduce ambiguity it didn't take much convincing for me to get started. A quick google search revealed this StackOverflow answer in which Robert Koritnik shared his method of using T4 Templates to generate files for Enumerations generated from database lookup tables.

As always, let's see the finished solution first. Here's the T4 template from the StackOverflow answer:

<#@ template debug="true" hostSpecific="true" #>  
<#@ output extension=".generated.cs" #>  
<#@ Assembly Name="System.Data" #>  
<#@ import namespace="System.Data" #>  
<#@ import namespace="System.Data.SqlClient" #>  
<#@ import namespace="System.IO" #>  
<#@ import namespace="System.Text.RegularExpressions" #>  
<#  
    string tableName = Path.GetFileNameWithoutExtension(Host.TemplateFile);
    string path = Path.GetDirectoryName(Host.TemplateFile);
    string columnId = tableName + "ID";
    string columnName = "Name";
    string connectionString = "data source=.;initial catalog=DBName;integrated security=SSPI";
#>
using System;  
using System.CodeDom.Compiler;

namespace Services.<#= GetSubNamespace() #>  
{
    /// <summary>
    /// <#= tableName #> auto generated enumeration
    /// </summary>
    [GeneratedCode("TextTemplatingFileGenerator", "10")]
    public enum <#= tableName #>
    {
<#  
    SqlConnection conn = new SqlConnection(connectionString);
    string command = string.Format("select {0}, {1} from {2} order by {0}", columnId, columnName, tableName);
    SqlCommand comm = new SqlCommand(command, conn);

    conn.Open();

    SqlDataReader reader = comm.ExecuteReader();
    bool loop = reader.Read();

    while(loop)
    {
#>      /// <summary>
        /// <#= reader[columnName] #> configuration setting.
        /// </summary>
        <#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #>
<#  
    }
#>  }
}
<#+  
    private string Pascalize(object value)
    {
        Regex rx = new Regex(@"(?:[^a-zA-Z0-9]*)(?<first>[a-zA-Z0-9])(?<reminder>[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*)");
        return rx.Replace(value.ToString(), m => m.Groups["first"].ToString().ToUpper() + m.Groups["reminder"].ToString().ToLower());
    }

    private string GetSubNamespace()
    {
        Regex rx = new Regex(@"(?:.+Services\s)");
        string path = Path.GetDirectoryName(Host.TemplateFile);
        return rx.Replace(path, string.Empty).Replace("\\", ".");
    }
#>

Then, for every Enum we need generated, we create a t4 file with the enum name and place the following line of code in it:

<#@ include file="..\..\T4 Templates\EnumGenerator.ttinclude" #>  

I plugged this in to our application, added a few t4 files for enumerations we needed generated, and boom, it just worked. All my lookup tables were now perfect little enums.

So we chugged along for a little while, perfectly content with our newfound solution, until my teammate Stacy asked about these T4 Templates and what they actually, y'know, did. My response went something like:

Matt: Well, it works like this. The first line..... Uh.... Well, actually, this set of lines here does something really clever....

I had no idea what this code was doing. I knew what it resulted in (a set of Enums generated from database tables) but couldn't sufficiently explain to anyone, even myself, exactly how it did this, which I unquestionably should be able to do. This code snippet was a black box, unknown to me, and experience told me that if I don't know how something works I won't be able to fix it if it breaks.

So I needed to understand just what it was that this code snippet was doing. That's what I'm going to do here: break down the snippet so that I (and hopefully you readers) will better understand what is being accomplished.

So let's get started!

What are T4 Templates?

If I'm going to understand what the code is doing, I first need to understand what technology is being used. MSDN has this to say about T4 Templates:

In Visual Studio, a T4 text template is a mixture of text blocks and control logic that can generate a text file. The control logic is written as fragments of program code in Visual C# or Visual Basic. The generated file can be text of any kind, such as a Web page, or a resource file, or program source code in any language.

OK so, in my mind, T4 templates allow you to write code that will generate other code. Seems simple enough. But how does it do that?

Breaking Down The Template

Let's walk through this template and see if we can understand what it is doing.

<#@ template debug="true" hostSpecific="true" #>  
<#@ output extension=".generated.cs" #>  
<#@ Assembly Name="System.Data" #>  
<#@ import namespace="System.Data" #>  
<#@ import namespace="System.Data.SqlClient" #>  
<#@ import namespace="System.IO" #>  
<#@ import namespace="System.Text.RegularExpressions" #>  

This appears to be some kind of collection of using statements, but the <#@ syntax was throwing me off. MSDN states that this syntax is used to create "directives" which (more or less) tell the T4 template how to behave. In our case, this template will cause the generated file to end in ".generated.cs" and imports several namespaces that we will need this template to use.

<#  
    string tableName = Path.GetFileNameWithoutExtension(Host.TemplateFile);
    string path = Path.GetDirectoryName(Host.TemplateFile);
    string columnId = tableName + "ID";
    string columnName = "Name";
    string connectionString = "data source=.;initial catalog=DBName;integrated security=SSPI";
#>

Now we start to see the meat of the template. The <# syntax is a boundary that specifies that anything within it is code running within the template (not the output code being generated). In our particular case, we are getting the name of the database table from the name of the file, which implies that each .tt file we want for each generated enum needs to be named the same as the database table.

We're also setting up the common values for the ID column and Name column, and getting our connection string ready. Just a bunch of setup here.

using System;  
using System.CodeDom.Compiler;

namespace Services.<#= GetSubNamespace() #>  
{

IMO this is the first truly interesting snippet. Given what I know about how T4 templates work (read: nothing) this snippet appears to be outputting actual code into the target file. Specifically, this is outputting two using statements and a namespace.

Since we're here, let's go ahead and examine the GetSubNamespace method:

private string GetSubNamespace()  
{
    Regex rx = new Regex(@"(?:.+Services\s)");
    string path = Path.GetDirectoryName(Host.TemplateFile);
    return rx.Replace(path, string.Empty).Replace("\\", ".");
}

Now I'm no regular expressions whiz-kid or anything (it looks like a bunch of gobbeldy-gook to me), but this appears to be using the folder structure where this file is located and transforming that structure into a namespace, which works very well for Visual Studio application since that's pretty much what VS does anyway. I'd be hard-pressed to explain exactly how it does this, though.

Back to the main portion of the code, specifically the first part emitted within the namespace declaration:

/// <summary>
    /// <#= tableName #> auto generated enumeration
    /// </summary>
    [GeneratedCode("TextTemplatingFileGenerator", "10")]
    public enum <#= tableName #>
    {
<#  
    SqlConnection conn = new SqlConnection(connectionString);
    string command = string.Format("select {0}, {1} from {2} order by {0}", columnId, columnName, tableName);
    SqlCommand comm = new SqlCommand(command, conn);

    conn.Open();

    SqlDataReader reader = comm.ExecuteReader();
    bool loop = reader.Read();

    while(loop)
    {
#>      

Now we start seeing the <# syntax again. The first time we see it is when it uses the tableName to output some comments about the generated enumeration. After that, we set up a SqlConnection, select from the appropriate table, and use a SqlDataReader to parse the results. What we do with those results is in the next snippet:

    while(loop)
    {
#>      /// <summary>
        /// <#= reader[columnName] #> configuration setting.
        /// </summary>
        <#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #>
<#  
    }
#>  }
}

For each of the values in the SqlDataReader, we output an enumeration value that uses the name found in the Name column in the table, after that name is run through a method called Pascalize(). Here's the implementation for Pascalize():

private string Pascalize(object value)  
{
    Regex rx = new Regex(@"(?:[^a-zA-Z0-9]*)(?<first>[a-zA-Z0-9])(?<reminder>[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*)");
    return rx.Replace(value.ToString(), m => m.Groups["first"].ToString().ToUpper() + m.Groups["reminder"].ToString().ToLower());
}

Oh goody, regexes again (/sarcasm). I'm inferring somewhat here, but Pascalize() appears to transform strings into Pascal-cased objects. So, if the value of Name was

movie theatre or cinema  

Pascalize would transform that string into:

MovieTheatreOrCinema  

and this conforms to the naming conventions for enumerations. I do wonder how Pascalize strips out non-alphanumerics (since that is what the "(?:[^a-zA-Z0-9]*)" portion of the regular expression appears to be doing), but that investigation is for a later time.

Summary

When I started writing this post, I knew thismuch about how T4 templates worked. Now I know a little more, and all it took was a bit of intuition, some luck, and some googling.

The point of all this is simple: you learn by discovering, by guessing, by failing, and by succeeding. It is part of my job to understand what the code that my group is using actually does, and when I didn't know enough, I had to stumble around for a bit before understanding came to me. Don't be afraid to admit you don't know something, since you can always learn it!

Regular expressions, though.... not sure I'll ever understand that nonsense.

Happy Coding!

Serializing Enums in ASP.NET Web API

Coming from a WCF world, I frequently used a contract-sharing trick that allowed both client and server to use the same set of DataContracts. This was especially important when we starting using Enums to better describe what certain values meant because the client and server could now both inherently have the same meaning for the same value.

Of course, Web API is not the same beast as WCF, and we cannot have anything resembling a "contract" to share between client and server. Without that shared definition, how can we handle enum values in our Web API calls in such a way as to preserve meaning? The answer is easier than you probably think it is.

Background

First off, you need to know that as far as Web API is concerned, enumerations are not special. They're just values of some kind (usually integers) that can be serialized like anything else. The only reason enumerations have meaning of any kind is because programmers impart meaning upon them.

What this means is that Web API has no special handling in place for enumerations. Instead, it expects the programmers to handle them however they need to, and in this post that's exactly what we're going to do. Let's find out how to serialize enumerations in ASP.NET Web API!

Serialize Meaning, Not Value

Imagine that we have the following enumeration:

public enum Language  
{
    English,
    French,
    Spanish,
    Russian,
    German,
    Mandarin,
    Cantonese,
    Farsi,
    Zulu
}

We might also have the following class:

public class Person  
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Language PrimaryLanguage { get; set; }
}

Finally, we could have an action in our ValuesController that looks like this:

[Route("Person")]
[HttpGet]
public Person Get()  
{
    var person = new Person()
    {
        FirstName = "John",
        LastName = "Smith",
        PrimaryLanguage = Language.English
    };
    return person;
}

If we hit this action (/values/person) in a browser, what is the resulting JSON response?

{"FirstName":"John","LastName":"Smith","PrimaryLanguage":0}

Well, we got a person back, sure enough. But imagine that if we are the client, and we make this call, what does 0 actually signify? 0 has no inherent meaning; it's just a magic number that could mean, well, anything really. So how do we get the meaning represented by this value?

What we can do is return the name of the enumeration rather than the value. Assuming our enums are named properly and descriptively (which could be a big assumption), this allows us to fight ambiguity and relay meaning to the client.

Web API uses JSON.net natively, so we can take advantage of the JSON.net converters. One such converter is StringEnumConverter, which happens to do exactly what we want; namely, take an enumeration and serialize it to its name, not its value. There are three possible ways we can tell JSON.net to serialize an enum to its name; the difference between them is what kind of scope we wish to use.

Solution #1: Decorate the Class Property

public class Person  
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    public Language PrimaryLanguage { get; set; }
}

This notifies JSON.net to only serialize this property to the enumeration name. This solution has the smallest scope, as only this particular property of this particular class we be serialized to the enumeration name rather than the value. What if we want to do this for all instances of a single enumeration? The second solution will do that for us.

Solution #2: Decorate the Enumeration

[JsonConverter(typeof(StringEnumConverter))]
public enum Language  
{
    English,
    French,
    Spanish,
    Russian,
    German,
    Mandarin,
    Cantonese,
    Farsi,
    Zulu
}

This commands JSON.net to serialize all instances of this enumeration to their name; anytime this enum is serialized, you'll values English and Farsi instead of 0 and 7.

However, what if we always want the name serialized rather than the value? That's where the third solution comes in handy.

Solution #3: Add the Converter Globally

The third solution makes all enumerations serialize to their name wherever they are used. We would do this by modifying the WebApiConfig file:

public static void Register(HttpConfiguration config)  
{
    // Web API configuration and services
    config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());

    // Web API routes
}

Now, any time the converter encounters an enumeration that needs to be serialized, it will do so using that enumeration's name rather than its value.

POSTing an Enum by Name

The three solutions above nicely handle scenarios in which we are returning enumerations to the client, but what about situations where the client wants submit an enumeration value to the server? Of course, they could submit such a value like so:

/values/sendLanguage/2

But, again, there's no meaning attached to the value 2. If the users wanted to use a URL that used the name of the language, how would we handle that?

/values/sendLanguage/English

All we would need to do is use Enum.TryParse like so:

[Route("SendLanguage/{language}")]
[HttpPost]
public Language? SendLanguage(string language)  
{
    Language parsedLanguage;
    if(Enum.TryParse<Language>(language, true, out parsedLanguage))
    {
        return parsedLanguage;
    }
    return null; //error, not a valid language
}

(Note that the boolean true in the TryParse call makes the parsing case-insensitive).

I imagine that this kind of thing would be the most useful in searching or filtering scenarios, where the client wants to find all people in a database that speak English or something similar. With this type of solution (and good naming guidelines) it should be simple to determine what the value of an enumeration is without resorting to the use of magic numbers.

These are all the rules I've come up with for handling and serializing enumerations in ASP.NET Web API. Check out the sample project on GitHub; it has all of these demos included.

Do you have any guidelines for handling enumerations in Web API that I might have missed? Let me know in the comments!

Happy Coding!

Best Practices: Fight Code Ambiguity with Enumerations

I've written before about the idea that code needs to have a reason to exist. Right alongside that idea is another I frequently find myself having to be reminded of: code must have a clear, explicit meaning.

Let me clarify what I mean by that (irony alert!). I think that a reason to exist and meaning are two distinct ideas. In my mind, having meaning gives the code purpose and importance (much like it does for humans). Funny thing is, many coders don't put enough effort into revealing the meaning of their code to their fellow developers. The absence of meaning leads to one of the most dangerous enemies a programmer will ever have to face: a monster known to as Ambiguity.

How do you slay this beast? There are many avenues to take, and one of them is to wield a weapon known to us programmers as Enumerations.

Ambiguity: the Programmer's Terror

Consider the following line of code:

var value = DownloadFile("FileName.pdf", true);  

After reading this line, we immediately have a problem: we don't know what true actually means! We know (or can reasonably assume) what the DownloadFile() method is supposed to do, and the first parameter looks like a filename, but what in the world does that second parameter represent? We have no idea, and now we have to dig down further to find out. Digging into this particular method won't take much time, but if we're having to do it on tens or hundreds of different methods in a given day it gets exhausting rather quickly.

Let us also consider this scenario:

var success = UploadFile("FileName.pdf", content, 1, 5, 12);  

That's even worse than the previous one! What do 1, 5, 12, mean? Size, number of pages, type of file? We can't determine that from just reading this snippet. Worse, anybody who comes along and needs to make changes to this code is less likely to actually follow through, since they'll probably have to know what the values mean in order to feel comfortable making changes and they won't have easy access to that knowledge. Not only does this snippet have awful readability, it indirectly hampers developers' ability to make the code better.

The monster Ambiguity has reared it's ugly head in these two examples, spitting fire and promising doom. So what do we do about it? We pick up the mighty sword known as Enumerations and use it to cut the head off of the beast.

The Best Defense is a Good Enum

Enumerations (aka Enums) are a construct in .NET used to provide a value with a name. By naming our Enums properly and clearly, we can give meaning to otherwise meaningless values.

An example Enumeration might look like this:

public Enum HistoryType  
{
    Standard,
    Detailed,
    Exempt
}

Note that Enumerations in .NET, by default, start at value 0 and increment. So for HistoryType, Standard has value 0, Detailed has value 1, and Exempt has value 2. If we wanted to set specific values, we can do so like this:

public Enum HistoryType  
{
    Standard = 1,
    Detailed = 4,
    Exempt = 9
}

If we wanted to update the code snippets we saw earlier to use Enumerations, we might do so like this:

var value = DownloadFile("FileName.pdf", FileDownloadMethod.NewTab);

var value2 = UploadFile("FileName.pdf", content, HasDescription.Yes, HistoryType.Exempt, EmailTarget.Executives);  

I'm a huge fan of Enumerations, and I think these examples nicely illustrate why. Since we've refactored the two bad examples from earlier into using Enums, we can now tell exactly what they do without needing to dive any further. We've saved ourselves precious time by just taking a bit more time to clearly explain what these values mean.

There's two situations in which using Enumerations is almost always the best option:

  1. When you would otherwise be passing a boolean parameter to a function
  2. When you would otherwise be using a magic number.

There's no reason to let Ambiguity rule your code when the sword of Enumerations can be wielded so easily. Use it wisely, and you too shall be endowed with the skills to fell this mighty beast.

Or, at least, write cleaner code. Whatever works for you.

Happy Coding!