ready to use uint route constraint?

a 夏天 提交于 2020-06-16 18:37:14

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!