问题
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.
回答1:
Does a ready to use uint route constraint exist?
No.
Based on the currently available documentation.
The ASP.NET Core Constraints folder provides good examples of creating a constraints
Reference Routing in ASP.NET Core: Custom route constraints
If you review the built in constraints you will see that they follow similar formats and checks for null.
After reviewing IntRouteConstraint, for example, I noticed some checks that were not in your example.
It is possible that
values.TryGetValue(routeKey, out object routeValue)
can result in routeValue
being null.
As for the additional null checks, one ideally only needs to check the parameters one intends to use within the scope of the current function.
Refactored code:
public class UIntRouteConstraint : IRouteConstraint {
public bool Match(HttpContext httpContext, IRouter route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection) {
if (routeKey == null)
throw new ArgumentNullException(nameof(routeKey));
if (values == null)
throw new ArgumentNullException(nameof(values));
if (values.TryGetValue(routeKey, out object routeValue) && routeValue != null) {
if (routeValue is uint)
return true;
string valueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
return UInt32.TryParse(valueString, out uint _);
}
return false;
}
}
来源:https://stackoverflow.com/questions/62211646/ready-to-use-uint-route-constraint