冲突的 MVC Web Api 路由

Conflicting MVC Web Api Routes

我们目前的数据设置如下:

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

相当多的对象派生自基础 class 任务。我们已经构建了 API 来管理这些对象,但也有一些共享功能,我试图将这些功能放入基础 api 控制器中,供每个单独的对象 api 继承。

像这样

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/GetAffectedCIs?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 }
            );
 }

我不太明白这里发生了什么。

有什么建议吗?

干杯。

您使用错误的 API URL 从 事件控制器 .

调用操作方法

Action 方法包含 id 作为参数,但是当您通过 API URL 调用它时,您使用的是 number 作为参数名称。

这个URL,向右打API因为Idnumber的参数类型相同,但是给Id传递了空值,因为 你需要在 API URL.

中使用 number 而不是 id

要调用写在Task Controller中的Action方法,你可以使用

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

要调用写在Incident Controller中的action方法,你可以使用

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

希望我的回答能解决您的问题

@Prasad Telkikar 在他的回答中提到了为什么它会与路由发生冲突。

您可以对 GetAffectedCIs 操作的 Route 值进行细微更改,如 [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)
    {
        ......
    }
}

根据 Karan 和 Prasad 的反馈,我实施了以下解决方案:

事件控制器:

[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);
    }
}

任务控制器:

[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);
    }
}

这个有效:)