准备好使用 uint 路由约束了吗?

ready to use uint route constraint?

我有一个 .NET Core Web API 项目,我的 ID 是从 1 开始的整数。在大多数示例中,我看到这样的东西

[HttpGet("{id:int}")]
public async Task<ActionResult<User>> GetUserByIdAsync([FromRoute] int id)
{
    // ...
}

因为我知道 ID 必须大于 0,所以我还添加了 :min(1) 路由约束。但是,将整数数据类型更改为 uint 不是更好吗?路线将是

"{id:uint:min(1)}"

并且方法参数将变为

[FromRoute] uint id

但不幸的是,uint 约束不存在。我认为当不为 ID 使用 GUID 时,这是一个标准问题,因为数据库将自动生成从 1 开始的整数 ID。我尝试创建自己的路由约束:

Startup 文件中,我在 services.AddControllers()

之后将其添加到 ConfigureServices 方法中
services.Configure<RouteOptions>(routeOptions =>   
{  
    routeOptions.ConstraintMap.Add("uint", typeof(UIntRouteConstraint));  
});

并且路由约束本身非常简单

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;
    }
}

在通过 id url 调用获取用户进行测试时,这似乎按预期工作。但是我不确定这个约束是否是防弹的,我之前是否需要那些空检查。

是否存在现成的 uint 路由约束?我想我不是唯一需要这个的人。

Does a ready to use uint route constraint exist?

没有

基于当前可用的文档。

The ASP.NET Core Constraints folder provides good examples of creating a constraints

引用Routing in ASP.NET Core: Custom route constraints

如果查看内置约束,您会发现它们遵循相似的格式并检查是否为空。

例如,在查看 IntRouteConstraint 之后,我注意到您的示例中没有一些检查。

有可能

values.TryGetValue(routeKey, out object routeValue) 

可能导致 routeValuenull

至于额外的空检查,理想情况下只需要检查打算在当前函数范围内使用的参数。

重构代码:

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;
    }
}