In gitclub-dotnet I wanted to use enumerations in routes. This can easily be
done by implementing an IRouteConstraint
. So let's do it!
All code can be found in a Git repository at:
Implementing the EnumRouteConstraint
We start by implementing a IRouteConstraint
, which will be used for matching incoming routes.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace GitClub.Infrastructure.Mvc
{
public class EnumRouteConstraint<TEnum> : IRouteConstraint
where TEnum : struct
{
public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
var matchingValue = values[routeKey]?.ToString();
return Enum.TryParse(matchingValue, true, out TEnum _);
}
}
}
We then need to configure the RouteOptions
for ASP.NET MVC like this:
// Route Constraints
builder.Services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("TeamRoleEnum", typeof(EnumRouteConstraint<TeamRoleEnum>));
options.ConstraintMap.Add("OrganizationRoleEnum", typeof(EnumRouteConstraint<OrganizationRoleEnum>));
options.ConstraintMap.Add("RepositoryRoleEnum", typeof(EnumRouteConstraint<RepositoryRoleEnum>));
});
Using the EnumRouteConstraint
And we can then use the Route Constraint like this:
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// ...
namespace GitClub.Controllers
{
[Route("[controller]")]
public class OrganizationsController : ControllerBase
{
// ...
[HttpPut("{organizationId}/organization-roles/users/{userId}/{role:OrganizationRoleEnum}")]
public async Task<IActionResult> AddUserOrganizationRole(
[FromServices] OrganizationService organizationService,
[FromServices] CurrentUser currentUser,
[FromRoute(Name = "organizationId")] int organizationId,
[FromRoute(Name = "userId")] int userId,
[FromRoute(Name = "role")] OrganizationRoleEnum role,
CancellationToken cancellationToken)
{
_logger.TraceMethodEntry();
// ...
}
// ...
}
}
And that's it!