One of the commenters on my blog posed an interesting question on my article about serializing enumerations in Web API:
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:
And here's the access levels:
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!