ASP.NET Web.api如何处理名称以GET开头的两个方法?

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

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

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

您的第一个Web API教程

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

注意:测试版的行为如上所述’匹配多种方法’ – RC和Release版本更多OCD。 如果存在多个潜在匹配,则会引发错误。 此更改消除了多个模糊匹配的混淆。 同时,它降低了我们在同一控制器中混合REST和RPC样式接口的能力,依赖于顺序和重叠路由。

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

WebAPI匹配语义

WebAPI使用的匹配语义非常简单。

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

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

例子

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

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

多重匹配方法 – 如果您有两个没有参数的Get方法会发生什么? GetStrawberry()GetOrange() 。 我可以告诉你,在你的代码中首先定义的函数(文件的顶部)赢得…奇怪。 这会产生副作用,使控制器中的某些方法无法访问(至少使用默认路由)….陌生人。

UPDATE

@WinFXGuy – 发表评论有点长,但……

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

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

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

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

如果您查看我的链接post,我会解释如何保留默认路由绑定,添加“子文件夹”并允许其他方法调用我需要GetAllProducts()GetSoldProducts()场景。

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

  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 

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

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

 [Route("api/products")] public IEnumerable GetAllProducts(){} [Route("api/products/sold")] public IEnumerable GetSoldProducts(){}