Ручное создание прозвища маршрута с персонализированным DirectRouteProvider вызывает ошибку “Многообразный actions were found that матч the request”

Я создаю услугу используя ASP.NET WebApi. Хочет добавить опору для переговоров типа содержимого, основанного на расширении в URI, так что я добавил следующее за кодом инициализации услуги:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    config.Formatters.JsonFormatter.AddUriPathExtensionMapping("json", "application/json");
    config.Formatters.XmlFormatter.AddUriPathExtensionMapping("xml", "application/xml");
  }
}

Для того, чтобы это функционировало, я нуждаюсь в том, чтобы создать два маршрута для каждого действия драйвера (я использую исключительно enrutamiento основано на признаках):

[Route("item/{id}/details")]
[Route("item/{id}/details.{ext}")]
[HttpGet]
public ItemDetail[] GetItemDetails(int id)
{
  return itemsService.GetItemDetails(id);
}

[Route("item/{name}")]
[Route("item/{name}.{ext}")]
[HttpPost]
public int CreateItem(string name)
{
  return itemsService.Create(name);
}

Это остается уродливым и способствует тому, чтобы код был без необходимости длиной, так что я исследовал способ добавлять маршрут с расширением, автоматически, когда будут верить в нормальный маршрут. Как результат я разработал персонализированное осуществление IDirectRouteProvider который я могу использовать, зарегистрировав признаки маршрута:

config.MapHttpAttributeRoutes(new AutomaticExtensionRouteProvider());

Код персонализированного поставщика:

public class AutomaticExtensionRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<RouteEntry> GetActionDirectRoutes(
      HttpActionDescriptor actionDescriptor,
      IReadOnlyList<IDirectRouteFactory> factories,
      IInlineConstraintResolver constraintResolver)
    {
        var result = base.GetActionDirectRoutes(actionDescriptor, factories, constraintResolver);
        var list = new List<RouteEntry>(result);
        foreach(var route in result.Where(r => !r.Route.RouteTemplate.EndsWith(".{ext}")))
        {
            var newTemplate = route.Route.RouteTemplate + ".{ext}";
            if (!result.Any(r => r.Route.RouteTemplate == newTemplate))
            {
                var entry = new RouteEntry(null, new HttpRoute(newTemplate,
                    new HttpRouteValueDictionary(route.Route.Defaults),
                    new HttpRouteValueDictionary(route.Route.Constraints),
                    new HttpRouteValueDictionary(route.Route.DataTokens)));
                list.Add(entry);
            }
        }
        return list.AsReadOnly();
    }
}

Проблема состоит в том, что это функционирует хорошо, но не удается в случае: Когда последняя часть маршрута - параметр без ограничений. Итак, в предыдущем примере, создании маршрутов для GetItemDetails функционируй, но для CreateItem брось следующее:

System.InvalidOperationException: Multiple actions were found that match the request: 
CreateItem on type FooBar.Api.Controllers.ItemsController
CreateItem on type FooBar.Api.Controllers.ItemsController
   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)
   at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)

Я представляю себе, откуда может приходить проблема: Произвольная цепь истекает главные файлы {name} и {name}.{ext}, а следовательно механизм WebApi запутывается, попробовав выбирать подходящий маршрут. Но тогда: Почему оно функционирует, когда определяются два маршрута ясно в признаках? А следовательно я понимаю, маршрут, в который я верю в классе AutomaticExtensionRouteProvider она идентична той, которая создается ясно с признаком (и если я отлаживаю, я вижу, что он действительно так).

Итак: Что происходит здесь?

31
задан 08.07.2019, 00:36
1 ответ

Я нашел решение.

Оказывается, что маршруты считают распределенным числовое распределенное предшествование, которое механизм enrutamiento WebApi использует, чтобы решать, какой маршрут использовать в случае конфликта. У маршрутов, созданных автоматически для того же действия всегда есть отличное предшествование: но у маршрута, который я создавал вручную, было то же предшествование, что и уже существующая!

Итак решение состоит в том, чтобы добавлять следующее в GetActionDirectRoutes, немедленно после new RouteEntry:

entry.Route.DataTokens["precedence"] = 
    ((decimal)route.Route.DataTokens["precedence"]) - 0.1M;
25
ответ дан 01.12.2019, 08:18
  • 1
    ... и aqu и # 237; у нас есть наш первый ответ.:-) – Konamiman 29.10.2015, 21:14
  • 2
    он этот первый d ela листает? – theboshy 10.08.2017, 00:34