如何设置ASP.NET Web Api路由约束HTTP状态返回码

问题描述 投票:3回答:3

我正在使用ASP.NET Web Api 2框架并使用如下的基本路由约束。

    [Route("Number/{id:int:min(2):max(10)}")]
    public HttpResponseMessage GetNumber([FromUri] int id)
    {
        return (id > 0)
            ? Request.CreateResponse(HttpStatusCode.OK, id)
            : Request.CreateResponse(HttpStatusCode.PreconditionFailed);
    }

我想知道当id与上面的约束,.eg 1或11冲突时,我如何覆盖默认的HTTP Status Return代码404?

非常感谢。

asp.net-web-api asp.net-web-api2 asp.net-web-api-routing
3个回答
8
投票

您可以创建自定义路径约束,以便按照您的意愿检查最小值,最大值,并且还允许您在未正确满足约束的情况下指定HttpStatusCode

public class RangeWithStatusRouteConstraint : IHttpRouteConstraint
{
    private readonly int _from;
    private readonly int _to;
    private readonly HttpStatusCode _statusCode;

    public RangeWithStatusRouteConstraint(int from, int to, string statusCode)
    {
        _from = from;
        _to = to;
        if (!Enum.TryParse(statusCode, true, out _statusCode))
        {
            _statusCode = HttpStatusCode.NotFound;
        }
    }

    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values,
        HttpRouteDirection routeDirection)
    {
        object value;
        if (values.TryGetValue(parameterName, out value) && value != null)
        {
            var stringValue = value as string;
            var intValue = 0;

            if (stringValue != null && int.TryParse(stringValue, out intValue))
            {
                if (intValue >= _from && intValue <= _to)
                {
                    return true;
                }

                //only throw if we had the expected type of value
                //but it fell out of range
                throw new HttpResponseException(_statusCode);
            }
        }

        return false;
    }
}

现在您需要在属性映射中注册它:

        var constraintResolver = new DefaultInlineConstraintResolver();
        constraintResolver.ConstraintMap.Add("rangeWithStatus", typeof(RangeWithStatusRouteConstraint));
        config.MapHttpAttributeRoutes(constraintResolver);

你的路线现在看起来像这样:

public class MyController : ApiController
{
    [Route("Number/{id:int:rangeWithStatus(2, 10, PreconditionFailed)}")]
    public HttpResponseMessage GetNumber([FromUri] int id)
    {
        return Request.CreateResponse(HttpStatusCode.OK, id);
    }
}

在这种情况下, ConflictHttpStatusCode.Conflict枚举的字符串表示形式,稍后将其强制转换为约束中的枚举值。

使用此类设置,如果值超出[2,10]范围,则​​Web API基础结构将使用409状态代码而不是默认值404进行响应。


5
投票

删除路径上的约束,并在方法内执行验证。

约束用于确定是否应该使用路径,但是如果输入超出某些参数,则希望使用要命中的路径但更改状态代码。

[Route("Number/{id})] // No constraints
public HttpResponseMessage GetNumber([FromUri] int id)
{
    return (id > 1 && id < 11) // here you validate id range
        ? Request.CreateResponse(HttpStatusCode.OK, id)
        : Request.CreateResponse(HttpStatusCode.PreconditionFailed);
}

1
投票

我认为正确的解决方案是检查控制器内的约束(如@aanund建议的那样)。 但是,如果要保留Route约束并避免代码中的条件,则可以创建具有相同路径但没有约束的另一个动作控制器。 如果未验证约束,则将调用新的操作控制器:

[Route("Number/{id:int:min(2):max(10)}")]
public HttpResponseMessage GetNumber([FromUri] int id)
{
    Request.CreateResponse(HttpStatusCode.OK, id)
}

[Route("Number/{id}")]
public HttpResponseMessage GetNumber2([FromUri] int id)
{
    Request.CreateResponse(HttpStatusCode.PreconditionFailed);
}
© www.soinside.com 2019 - 2024. All rights reserved.