8

我正在查看 Microsoft 的以下教程。根据本教程,

在第一个示例中,“products”匹配名为 ProductsController 的控制器。该请求是一个 GET 请求,因此框架会在 ProductsController 上查找名称以“Get...”开头的方法。此外,URI 不包含可选的 {id} 段,因此框架会寻找不带参数的方法。ProductsController::GetAllProducts 方法满足所有这些要求。

如果有两种方法,如 GetAllProducts() 和 GetSoldProducts(),会发生什么?两者都没有参数。

您的第一个 Web API 教程

4

3 回答 3

12

对于这个特定问题,有两种可能的解决方案:

  1. 更改 MapHttpRoute 调用以要求指定操作的名称。(我使用自托管语法):

        config.Routes.MapHttpRoute(
                "API Route 1",
                "api/{controller}/{action}");
    
        config.Routes.MapHttpRoute(
                "API Route 2",
                "api/{action}",
                new { controller = "products" });
    

    所以你的http客户端会调用:

    api/products/GetAllProductsapi/GetAllProducts api/products/GetSoldProductsapi/GetSoldProducts

    见: http ://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

  2. 将每个方法放在一个单独的控制器(ProductsController、SoldProductsController)中。所以你会打电话api/productsapi/soldproducts得到你的结果。


相关主题... 在您有多个 Get 操作且具有相同类型的单个原始参数的情况下,ASP.NET Web API 将查看参数的名称以解析要调用的重载操作。

例如,如果您有两个操作:

GetProductByName(string name) 
GetProductByCategory(string category) 

您的 http 客户端可以调用

api/products?name=hammer 
api/products?category=toys

并且路由引擎将调用正确的操作。

于 2012-06-21T20:54:59.237 回答
8

假设您使用的是默认路由,简短的回答是:将调用您的类的第一个(在顶部)定义的方法。另一种方法是无法访问的。

注意:测试版在“匹配多种方法”方面的表现与上述相同——RC 和发布版本有点强迫症。如果有多个潜在匹配项,则会引发错误。此更改消除了多个不明确匹配的混淆。同时,它降低了我们在同一个控制器中混合 REST 和 RPC 样式接口的能力,依赖于顺序和重叠的路由。

从我写的关于该主题的另一篇文章中大量窃取:

WebAPI 匹配语义

WebAPI 使用的匹配语义相当简单。

  1. 它将动作的名称与动词匹配(动词 = get?查找以“get”开头的方法)
  2. 如果传递了参数,则 api 会寻找带有参数的操作

因此,在您的代码示例中,不带参数的 GET 请求与不带参数的Get*( )函数匹配。包含和 ID 的 Get 查找Get***(int id).

例子

虽然匹配语义很简单,但它给 MVC 开发人员(至少这个开发人员)造成了一些混乱。让我们看一些例子:

奇数名称- 您的 get 方法可以命名为任何名称,只要它以“get”开头。因此,在小部件控制器的情况下,您可以命名您的功能GetStrawberry(),它仍然会匹配。将匹配想象为: methodname.StartsWith("Get")

多种匹配方法- 如果您有两个没有参数的 Get 方法会发生什么? GetStrawberry()GetOrange()。据我所知,代码中首先定义的函数(文件顶部)胜出……奇怪。这具有使控制器中的某些方法无法访问的副作用(至少使用默认路由)......陌生人。

更新

@WinFXGuy - 发表评论有点长,但是......

不要妄下结论!我试图回答你提出的问题,但这只是故事的一半。您可以做很多事情来更改默认行为。

首先,WebAPI 支持大部分oData规范。如果您冒泡IQueryable到您的控制器,oData 参数将自动与查询对象集成。它采用$filter,$top和等参数$skip。因此,在您的情况下,您可以编写一种方法并传递类似$filter=sale_date neq null.

此外,您可以应用该[ResultLimit]属性来防止人们要求 150 亿条记录。

其次,您可以修改路线。默认路由针对的是 RESTful api,通常每个实体有 1 个控制器。您可以更改路由并使其成为 RPC 样式。

如果您查看我的链接帖子,我将解释我如何保留默认路由绑定、添加“子文件夹”以及在我需要的情况下允许额外的方法调用GetAllProducts()GetSoldProducts().

于 2012-05-18T19:35:55.187 回答
4

添加答案以反映最新版本的 Web API 原生支持[Route]属性

[Route("api/products")]
public IEnumerable<Product> GetAllProducts(){}

[Route("api/products/sold")]
public IEnumerable<Product> GetSoldProducts(){}
于 2015-05-12T17:27:02.963 回答