如何在asp.net中定义WebAPI路由

时间:2018-02-06 14:43:19

标签: asp.net asp.net-web-api

背景

我有一个控制器

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

3 个答案:

答案 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)

我建议你使用路由属性。为什么呢?

  1. 它永远不会给你带来任何麻烦,比如你所描述的模式。
  2. 它比模式更具可读性。

    [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

发出请求

但是,它出现在基于属性的路由中,替代形式不起作用,也就是说,我无法使用以下命令:

http://localhost:62793/api/WorkOrders/?workCentreID=ABC