Asp.Net Core Enum route constraints

The Asp.Net Core routing system makes it really easy for us to map complex routes to specific controller actions. The really nice thing that I like about Asp.Net Core routing is the ability to constrain routes by their parameter types, for example:

/products/21

maps to the route pattern:

"products/{id:int}"

and the parameter id is parsed as an int and available to use in the Action.

There are a number of useful route constraints available to us out-of-the-box, such as int, bool, datetime, decimal, guid, length, range, required, regex, all of which are super useful, but one that is clearly missing is any Enum types.

If we want to constrain a route parameter so that it accepts an Enum type, we need to roll our own route constraint. This is fairly simple, and takes only three steps:

1. Create the Route Constraint

In your Asp.Net Core application, create a new class that implements IRouteConstraint:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using System;
namespace MyWebApp
{
public class MyRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
// TODO: this is where we evaluate the parameter
}
}
}

IRouteConstraint defines one method, Match, which evaulates the routing information and returns true or false, depending on whether the constraint satisfied.

The values parameter provides all of the route values that have been provided to the current route, and the routeKey parameter is the name of the current parameter that is being matched. The steps are to retrieve the value of the item in the values object with the key of routeKey, and return true if this is the required Enum type:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using System;
namespace MyWebApp
{
public class MyRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
// retrieve the candidate value
var candidate = values[routeKey]?.ToString();
// attempt to parse the candidate to the required Enum type, and return the result
return Enum.TryParse(candidate, out MyEnum result);
}
}
}

Now that we have created the Route Constraint, we need to register it so that the routing engine knows about it.

2. Register the Route Constraint

In the Startup.cs file, add this block:

public void ConfigureServices(IServiceCollection services)
{
  ...
  services.Configure<RouteOptions>(options =>
  {
    options.ConstraintMap.Add("myEnum", typeof(MyRouteConstraint));
  });
  ...
}

“myEnum” can be any string, and it is what the routing engine looks for in the route patterns to trigger matching with this constraint. Make it something memorable and clear.

3. Add your route constraint to your routes

For example, in a routing attribute:

[Route("products/{category:myEnum}")]
public IActionResult GetProductsByCategory(MyEnum category)
{
  ...
}

Leave a comment

search previous next tag category expand menu location phone mail time cart zoom edit close