冲突的 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因为Id
和number
的参数类型相同,但是给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);
}
}
这个有效:)
我们目前的数据设置如下:
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因为Id
和number
的参数类型相同,但是给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);
}
}
这个有效:)