【问题标题】:How to define WebAPI route in asp.net如何在 asp.net 中定义 WebAPI 路由
【发布时间】:2018-02-06 14:43:19
【问题描述】:

背景

我有一个控制器

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

这按预期工作,我可以导航到上面的示例 URL。

问题

现在我想用一种方法创建另一个控制器,如下所示:

public class FilteredWorkOrderController : ApiController
{

        //By WorkCentreID = ABC, XYZ, UVW
        public IEnumerable<WhateverObj> Get(string workCentreID)
        {
        //etc...
        }
}

下面的网址点击上面的方法ok。

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

但是(替代)形式

http://localhost:62793/api/FilteredWorkOrder/ABC

不起作用,错误信息是:

{"Message":"找不到与请求 URI 'http://localhost:62793/api/FilteredWorkOrder/ABC'匹配的 HTTP 资源。","MessageDetail":"在控制器 'FilteredWorkOrder' 上找不到与请求匹配的操作。"}

我需要什么路由映射配置才能使替代 URI 也可以工作?

我试过了

    config.Routes.MapHttpRoute(
        name: "FilteredApi",
        routeTemplate: "api/{controller}/{workCentreID}"
    );

但这不起作用。

我注意到在 Filtered 控制器中,如果我将 Get(string workCenterID) 中的参数名称更改为 Get(string id),那么两个 URL 都可以工作!

http://localhost:62793/api/FilteredWorkOrder/?id=ABC
http://localhost:62793/api/FilteredWorkOrder/ABC

参数名有什么神奇之处:'id'?

我希望我的参数被称为workCentreID

【问题讨论】:

  • 你研究过属性路由吗?这些天我倾向于使用它,因为它使路由接近受影响的代码。 docs.microsoft.com/en-us/aspnet/web-api/overview/…
  • 检查路线的顺序。更通用的路由应该出现在更有针对性或专门的路由之后,否则通用路由将捕获并处理用于其他路由的请求。因此,在您的情况下,您需要切换当前注册的路由的顺序,或者另一种选择是考虑使用属性路由参考Attribute Routing in ASP.NET Web API 2

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


【解决方案1】:

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) 对于第二种情况 - 如果您将自定义路由注册放在默认路由之前 - 您的 URL 应该可以工作:

 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 中描述路由

【讨论】:

  • 我会看这篇文章的,谢谢;将 FilteredApi 首先工作但会破坏其他东西; URL api/WorkOrder/123 总是最终到达 Get() 方法,就好像我在请求 api/WorkOrder;它看不到“id”参数
【解决方案2】:

cmets / answers 为我指明了使用基于属性的路由的正确方向。我需要的是

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

【讨论】:

    【解决方案3】:

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

    1. 它永远不会像您描述的模式那样给您带来任何麻烦。
    2. 它确实比模式更具可读性。

      [Route("{workCentreID}")]
      public IEnumerable<WhateverObj> Get(string workCentreID)
      {
      //etc...
      }
      

    【讨论】:

    • 属性路由解决了我的问题。但我不能接受你的回答,因为语法错误,例如,workcentreID 是一个参数,应该放在大括号中; [FromRoute] 真的存在吗?哪个类包含它,我需要参考什么。
    • @joedotnot 是的,你是对的。如果您使用 WebApi 2,则没有 [FromRoute] 属性,因为它是从 asp.net 核心出现的。我确定了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 2017-09-12
    相关资源
    最近更新 更多