Противоречивые маршруты MVC Web Api - PullRequest
0 голосов
/ 03 апреля 2019

В настоящее время у нас есть настройки данных, такие как:

Task
 -> Incident
 -> ....
 -> ....

Довольно много объектов являются производными от базового класса Task. Мы создали API для управления этими объектами, но у нас также есть некоторые общие функциональные возможности, которые я пытался поместить в базовый контроллер API, чтобы каждый отдельный объект API наследовал.

Like So

TaskController
 -> IncidentController
 -> ....
 -> ....

Это работает по большей части. Однако у меня есть проблема со следующим.

Внутри Incident Controller У меня есть Get Метод:

[RoutePrefix("Api/Incident")]
public class IncidentController : TaskController
{
    //Get an individual incident by ID
    [HttpGet]
    [Route("{id}")]
    public GenericIncidentGet Get(string id)
    {
        .....
    }
}

Этот метод отлично работает. У меня тогда есть метод на родительском контроллере

public class TaskController : ApiController
{
    [HttpGet]
    [Route("{number}")]
    public ListResponse<TaskCiResultFlat> GetAffectedCIs(string number)
    {
        ......
    }
}

Когда я вызываю вышеуказанный метод через / Api / Incident / GetActedCIs? Number = XXXX, он фактически вызывает метод Incident Get(), но с параметром null id.

В настоящее время я регистрирую эти маршруты WebApi:

public static void Register(HttpConfiguration config)
{
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
             "ActionIdApi", "api/{controller}/{action}/{id}/{id2}/{id3}/{id4}/{id5}/{id6}", new { id = RouteParameter.Optional, id2 = RouteParameter.Optional, id3 = RouteParameter.Optional, id4 = RouteParameter.Optional, id5 = RouteParameter.Optional, id6 = RouteParameter.Optional });


            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
 }

Я не могу понять, что здесь происходит.

Есть предложения?

Приветствие.

Ответы [ 3 ]

2 голосов
/ 03 апреля 2019

Вы используете неправильный URL-адрес API для вызова метода действия из Контроллер инцидентов .

Метод действия содержит id в качестве параметра, но когда вы вызываете его через URL-адрес API, выиспользуют number в качестве имени параметра.

Этот URL, обращающийся к правильному API, потому что тип параметра Id и number одинаков, но передаёт нулевое значение в Id, потому что вам нужно использовать number вместоid в URL API.

Для вызова метода Action, написанного в Task Controller , вы можете использовать

<BaseURL>/api/Task/Get?number=XXXX

Для вызова метода действия, написанного в Контроллер инцидентов , вы можете использовать

<BaseURL>/Api/Incident/GetAffectedCIs?id=XXXX

Надеюсь, мой ответ решит вашу проблему

1 голос
/ 03 апреля 2019

@ Прасад Телькикар упомянул в своем ответе, почему возникают конфликты с маршрутами.

Вы можете внести незначительные изменения в значение Route для действия GetAffectedCIs как [Route("GetAffectedCIs/{number}")], тогда оно будет работать.

Здесь /Api/Incident/GetAffectedCIs?number=XXXX будет соответствовать обоим API, но согласно Порядку маршрута [Route("GetAffectedCIs/{number}")] имеет Literal segments как GetAffectedCIs и имеет более высокий приоритет.

Для получения более подробной информации о Route Order вы можете обратиться https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#route-order.

Ваше полное действие будет таким, как показано ниже.

public class TaskController : ApiController
{
    [HttpGet]
    [Route("GetAffectedCIs/{number}")]
    public ListResponse<TaskCiResultFlat> GetAffectedCIs(string number)
    {
        ......
    }
}
0 голосов
/ 03 апреля 2019

Основываясь на отзывах Карана и Прасада, я реализовал следующее решение:

IncidentController:

[RoutePrefix("Api/Incident")]
public class IncidentController : TaskController
{
    //Get an individual incident by ID
    [HttpGet]
    public GenericIncidentGet Get(string id)
    {
        return GenericIncidentWf.GenericIncidentGet(ControllerContext.ControllerDescriptor.ControllerName, System.Threading.Thread.CurrentPrincipal.Identity.Name, id);
    }
}

TaskController:

[RoutePrefix("Api/Incident")]
public class IncidentController : TaskController
{
    //Get an individual incident by ID
    [HttpGet]
    public GenericIncidentGet Get(string id)
    {
        return GenericIncidentWf.GenericIncidentGet(ControllerContext.ControllerDescriptor.ControllerName, System.Threading.Thread.CurrentPrincipal.Identity.Name, id);
    }
}

Это работает :)

...