9

... думаю, я первый, кто спросит об этом?Было найдено несколько типов контроллеров, соответствующих URL. Это может произойти, если маршруты атрибутов на нескольких контроллерах соответствуют запрашиваемому URL-адресу

Скажет у вас есть следующие маршруты, каждый объявлено на другой контроллере:

[HttpGet, Route("sign-up/register", Order = 1)] 
[HttpGet, Route("sign-up/{ticket}", Order = 2)] 

... вы могли бы сделать это в MVC 5.0 с тем же кодом для параметра Order исключения. Но после обновления до MVC 5.1 вы получите сообщение об ошибке в заголовке вопроса:

Было найдено несколько типов контроллеров, соответствующих URL. Это может произойти, если маршруты атрибутов на нескольких контроллерах соответствуют запрошенному адресу .

Значит, новый RouteAttribute.Order собственности является только контроллером уровня? Я знаю, что в AttributeRouting.NET вы можете делать SitePrecedence. Единственный способ иметь маршруты, подобные приведенным выше, когда все действия находятся в одном контроллере?

Update

К сожалению, я должен был упомянуть эти маршруты на контроллерах MVC, не WebAPI. Я не уверен, как это влияет на ApiControllers.

+0

Взгляните на это, что сработало для меня. http://stackoverflow.com/questions/23094584/multiple-controller-types-with-same-route-prefix-asp-net-web-api/23097445?noredirect=1#23097445 – user1145404

+0

Это абсолютная катастрофа. Это сломало мой весь сайт. Есть ли какое-нибудь реальное решение? – BowserKingKoopa

+0

Можете попробовать regex: https://stackoverflow.com/questions/26806395/mvc-route-attribute-error-on-two-different-routes?rq=1 Также будет пытаться настроить ограничение маршрута: https: // blogs. msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/ – nmit026

ответ

13

В случае маршрутизации атрибутов веб-API пытается найти все контроллеры, которые соответствуют запросу. Если он видит, что несколько контроллеров способны справиться с этим, тогда он выдает исключение, поскольку считает, что это возможно ошибка пользователя. Это исследование маршрута отличается от обычной маршрутизации, где выигрывает первый матч.

Как обходной путь, если у вас есть эти два действия внутри одного контроллера, тогда Web API оценивает приоритет маршрута, и вы должны увидеть, что ваш сценарий работает.

+0

Выполняется ли ваш ответ на MVC-контроллеры в дополнение к WebAPI? – danludwig

+0

Да ... правильно ... это относится как к MVC & Web API ... –

+3

Нет ли другого способа сделать это и сохранить 2 действия в отдельных контроллерах? – franka

10

Если вы знаете, что ticket будет int вы можете указать, что тип в пути, чтобы помочь решить маршрут:

[HttpGet, Route("sign-up/register")] [HttpGet, Route("sign-up/{ticket:int}")]

Этот подход работает для меня, за комментарий user1145404, которая включает в себя ссылку Multiple Controller Types with same Route prefix ASP.NET Web Api

+0

Спасибо за ссылку на большой вопрос и ответ. –

+0

Это должен быть правильный ответ. Указанный тип более явный, понятный и позволяет разрешить эту проблему в контроллерах. Спасибо, этот ответ мне поможет :) – jross

1

Есть два способа исправить это:

регулярное выражение ограничения, как здесь: MVC Route Attribute error on two different routes

Или пользовательский маршрут ограничение, как здесь: https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

Вы можете создавать ограничения пользовательских маршрутов путем реализации интерфейса IRouteConstraint.Например, следующее ограничение ограничивает параметр для задания допустимых значений:

public class ValuesConstraint : IRouteConstraint 
{ 
    private readonly string[] validOptions; 
    public ValuesConstraint(string options) 
    { 
     validOptions = options.Split('|'); 
    } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     object value; 
     if (values.TryGetValue(parameterName, out value) && value != null) 
     { 
      return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase); 
     } 
     return false; 
    } 
} 

Следующий код показывает, как зарегистрировать ограничение:

public class RouteConfig 
{ 
    public static void RegisterRoutes(RouteCollection routes) 
    { 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     var constraintsResolver = new DefaultInlineConstraintResolver(); 

     constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint)); 

     routes.MapMvcAttributeRoutes(constraintsResolver); 
    } 
} 

Теперь вы можете применить ограничение в маршрутах:

public class TemperatureController : Controller 
{ 
    // eg: temp/celsius and /temp/fahrenheit but not /temp/kelvin 
    [Route("temp/{scale:values(celsius|fahrenheit)}")] 
    public ActionResult Show(string scale) 
    { 
     return Content("scale is " + scale); 
    } 
} 

На мой взгляд, это не большой дизайн. Нет никаких суждений о том, какой URL-адрес вы намереваетесь, и каких-либо правил специфики при сопоставлении, если вы явно не установили их самостоятельно. Но, по крайней мере, вы можете получить свои URL-адреса так, как хотите. Надеемся, что ваш список ограничений не слишком длинный. Если это так, или вы не хотите жестко кодировать параметр строки маршрута и его ограничения, вы можете создать его программно вне метода действия и передать его атрибуту Route в качестве переменной.

 Смежные вопросы

  • Нет связанных вопросов^_^