I have a .NET Core Web API project and my Ids are integers starting at 1. In most samples I see something like this
[HttpGet("{id:int}")]
public async Task<ActionResult<User>> GetUserByIdAsync([FromRoute] int id)
{
// ...
}
Since I know Ids must be greater than 0 I also added the :min(1)
route constraint. But wouldn't it be better to change the integer datatype to uint
? The route would then be
"{id:uint:min(1)}"
and the method parameter will change to
[FromRoute] uint id
but unfortunately the uint constraint does not exist. I think when not using GUIDs for Ids this is a standard problem because databases will autogenerate integer Ids starting at 1. I tried to create my own route constraint:
In the Startup
file I added this to the ConfigureServices
method after services.AddControllers()
services.Configure<RouteOptions>(routeOptions =>
{
routeOptions.ConstraintMap.Add("uint", typeof(UIntRouteConstraint));
});
and the route constraint itself is pretty straight forward
public class UIntRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
if (route == null)
throw new ArgumentNullException(nameof(route));
if (routeKey == null)
throw new ArgumentNullException(nameof(routeKey));
if (values == null)
throw new ArgumentNullException(nameof(values));
if (values.TryGetValue(routeKey, out object routeValue))
{
// check if param is a uint
return UInt32.TryParse(routeValue.ToString(), out uint number);
}
return false;
}
}
This seems to work as expected when testing it by calling the get user by id url. But I'm not sure if this constraint is bullet proof and if I need those null checks before.
Does a ready to use uint
route constraint exist? I think I'm not the only one needing this.