Пользовательское ограничение маршрута вызывается несколько раз или вызывается, когда ограничение вообще не упоминается
Я написал собственный маршрут, но обнаружил, что он вызвал методы Action, которые не указали ограничения в маршрутизации атрибута.
[RoutePrefix("api/v1/Orders")]
public class OrdersController : BaseController
{
[Route("{orderId}/archive")]
public HttpResponseMessage Put(Guid orderId, [FromBody]List<ComplexObject> c)
{
}
public HttpResponseMessage Get([FromUri]ComplexObject c)
{
}
[Route("{orderId:checkGuid(orderId,BadRequest)}/{personId:checkGuid(personId,BadRequest)}")]
public HttpResponseMessage Get(Guid orderId, Guid personId)
{
}
}
public class CheckGuidRouteConstraint : IHttpRouteConstraint
{
private readonly HttpStatusCode _statusCode;
private readonly string _parameterName;
private HttpStatusCode _default = HttpStatusCode.BadRequest;
public CheckGuidRouteConstraint(string parameterName,string statusCode)
{
if (!Enum.TryParse(statusCode, true, out _statusCode))
{
_statusCode = _default;
}
_parameterName = parameterName;
}
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
bool isRouteWrong = doSomeCheck();
if(isRouteWrong)
{
//throw custom exception with proper message
}
return true;
}
}
И добавил это в
var constraintResolver = new DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add("checkGuid", typeof(CheckGuidRouteConstraint));
config.MapHttpAttributeRoutes(constraintResolver);
Теперь, когда я обращаюсь к методу Put(), метод Match() маршрутного константэйта вызывается более 1 раза и в итоге завершается ошибкой. Обратите внимание, что я не упомянул никаких ограничений маршрута в моем атрибуте Put().
1 ответ
Этот способ не работает, если у вас много пользовательских IHttpRouteConstraint и контроллера с одинаковыми методами. Кажется, что WebAPI не анализирует параметры маршрута и просто пробует их все до того, как какой-либо из зарегистрированных IHttpRouteConstraint вернет true. Итак, если один из них выдает исключение, он автоматически прекращает обработку других ограничений. Если сначала было зарегистрировано плохое ограничение, вы получите ответ об ошибке, даже если это ограничение не используется в шаблоне маршрута.
[HttpGet]
[Route("{code:enum(System.Net.HttpStatusCode)}")]
public IHttpActionResult Enum(string code)
{
return Ok();
}
[HttpGet]
[Route("{period:values(days|weeks|months)}")]
public IHttpActionResult Value(string period)
{
return Ok();
}
например, если ограничение 'enum' имеет ту же реализацию, что и ваша, и зарегистрировано первым
constraintsResolver.ConstraintMap.Add("enum", typeof(EnumConstraint));
constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint));
config.MapHttpAttributeRoutes(constraintsResolver);
Значение action никогда не вернется Ok.