背景
我有一个控制器
public class WorkOrderController : ApiController
{
// GET: api/WorkOrder
public IEnumerable<WhateverObj> Get()
{
//etc..
}
// GET: api/WorkOrder/123
public WhateverObj Get(string id)
{
//etc..
}
// GET: api/WorkOrder/5/020
public WhateverObj Get(string id, string opID)
{
//etc...
}
}
以及以下路线:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ServicesApi",
routeTemplate: "api/{controller}/{id}/{opID}",
defaults: new { opID = RouteParameter.Optional }
);
这可以按预期工作,我可以导航到上面的示例网址。
问题
现在我想用一个方法创建另一个Controller,如下所示:
public class FilteredWorkOrderController : ApiController
{
//By WorkCentreID = ABC, XYZ, UVW
public IEnumerable<WhateverObj> Get(string workCentreID)
{
//etc...
}
}
以下网址点击上述方法确定。
http://localhost:62793/api/FilteredWorkOrder/?workCentreID=ABC
但是(替代)形式
http://localhost:62793/api/FilteredWorkOrder/ABC
不起作用,错误信息为:
{&#34;消息&#34;:&#34;未找到与请求URI匹配的HTTP资源&#39; http://localhost:62793/api/FilteredWorkOrder/ABC&#39;。&#34;,&#34; MessageDetail&#34;:&#34;在控制器上找不到任何操作&#39; FilteredWorkOrder&#39;与请求匹配。&#34;}
我需要什么路由映射配置才能使替代URI也起作用?
我试过
config.Routes.MapHttpRoute(
name: "FilteredApi",
routeTemplate: "api/{controller}/{workCentreID}"
);
但这不起作用。
我注意到在Filtered控制器中,如果我将Get(string workCenterID)
中的参数名称更改为Get(string id)
,则两个网址都有效!
http://localhost:62793/api/FilteredWorkOrder/?id=ABC
http://localhost:62793/api/FilteredWorkOrder/ABC
参数名称的神奇之处在于:&#39; id&#39;?
我希望我的参数被称为workCentreID
。
答案 0 :(得分:2)
1)路由模板中的参数名称应与您的操作的参数名称匹配。这是一个惯例。因此,当您在config中注册默认路由时:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ServicesApi",
routeTemplate: "api/{controller}/{id}/{opID}",
defaults: new { opID = RouteParameter.Optional }
);
并尝试请求http://localhost:62793/api/FilteredWorkOrder/ABC - 应用程序无法找到操作,因为没有模式匹配。
2)在配置中注册路由的顺序很重要。如果您有多个潜在的模式匹配,引擎将选择第一个。在更改之后,您在第二种情况下描述,引擎在路由表中查找并再次匹配url http://localhost:62793/api/FilteredWorkOrder/ABC的默认路由 - 这与操作签名无关。
3)对于第二种情况 - 如果您将自定义路线注册放在默认路线之前 - 您的网址应该有效:
config.Routes.MapHttpRoute(
name: "FilteredApi",
routeTemplate: "api/{controller}/{workCentreID}"
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
此外,take a look at this article,描述WEB API中的路由
答案 1 :(得分:0)
我建议你使用路由属性。为什么呢?
它比模式更具可读性。
[Route("{workCentreID}")]
public IEnumerable<WhateverObj> Get(string workCentreID)
{
//etc...
}
答案 2 :(得分:0)
评论/答案指出了我使用基于属性的路由的正确方向。我需要的是
public class FilteredWorkOrderController : ApiController
{
//By WorkCentreID = ABC, XYZ, UVW
[Route("api/WorkOrders/{workCentreID}")]
public IEnumerable<WhateverObj> Get(string workCentreID)
{
//etc...
}
}
我可以使用http://localhost:62793/api/WorkOrders/ABC
发出请求但是,它出现在基于属性的路由中,替代形式不起作用,也就是说,我无法使用以下命令: