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

本文关键字:开头 GET 方法 两个 何处理 api NET ASP 处理 Web | 更新日期: 2023-09-27 18:34:34

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

在第一个示例中,"产品"与名为 产品控制器。该请求是GET请求,因此框架 在名称以 "得..."。此外,URI 不包含可选的 {id} 段,因此框架会查找没有参数的方法。这 产品控制器::GetAll产品方法满足所有这些 要求。

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

您的第一个 Web API 教程

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

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

  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. 将每个方法放在单独的控制器(产品控制器、销售产品控制器(中。 因此,您可以致电api/productsapi/soldproducts以获取结果。


相关主题...如果有多个具有相同类型的基元参数的多个 Get 操作,则 Web API ASP.NET 查看参数的名称,以解析要调用的重载操作。

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

GetProductByName(string name) 
GetProductByCategory(string category) 

您的 HTTP 客户端可以调用

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

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

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

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

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

WebAPI 匹配语义

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

  1. 它将动作的名称与动词匹配(verb = get?查找以"get"开头的方法(
  2. 如果传递了参数,API 将使用参数查找操作

因此,在您的代码示例中,没有参数的 GET 请求与没有参数的 Get*( ) 函数匹配。 获取包含和 ID 查找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()的情况下调用其他方法。

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

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