我正在使用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何时与上述约束冲突,例如。 1或11, 如何覆盖默认的HTTP状态返回代码404?
非常感谢。
答案 0 :(得分: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);
}
}
在这种情况下Conflict
是HttpStatusCode.Conflict
枚举的字符串表示形式,稍后会转换为约束中的枚举值。
使用此类设置,如果值超出[2,10]范围,则Web API基础结构将使用409状态代码而不是默认值404进行响应。
答案 1 :(得分: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);
}
答案 2 :(得分: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);
}