具有多个参数的 Web API 路由

Posted

技术标签:

【中文标题】具有多个参数的 Web API 路由【英文标题】:Web API routing with multiple parameters 【发布时间】:2014-02-04 02:12:43 【问题描述】:

我正在研究如何为以下 Web API 控制器进行路由:

public class MyController : ApiController

    // POST api/MyController/GetAllRows/userName/tableName
    [HttpPost]
    public List<MyRows> GetAllRows(string userName, string tableName)
    
        ...
    

    // POST api/MyController/GetRowsOfType/userName/tableName/rowType
    [HttpPost]
    public List<MyRows> GetRowsOfType(string userName, string tableName, string rowType)
    
        ...
    

目前,我正在为 URL 使用此路由:

routes.MapHttpRoute("AllRows", "api/controller/action/userName/tableName",
                    new
                    
                        userName= UrlParameter.Optional,
                        tableName = UrlParameter.Optional
                    );

routes.MapHttpRoute("RowsByType", "api/controller/action/userName/tableName/rowType",
                    new
                    
                        userName= UrlParameter.Optional,
                        tableName = UrlParameter.Optional,
                        rowType= UrlParameter.Optional
                    );

但目前只有第一种方法(带有 2 个参数)有效。我是在正确的路线上,还是我的 URL 格式或路由完全错误?路由对我来说似乎是黑魔法......

【问题讨论】:

如何指定一个非可选参数?我希望第一个是必需的,第二个是可选的? 路由只是 IMO 在 webapiconfig 中做的更痛苦,请参阅我对 Route 属性路由的回答 【参考方案1】:

我已经看到 WebApiConfig 变得“失控”,其中放置了数百条路由

我个人更喜欢Attribute Routing

你把它与 POST 和 GET 混淆了

[HttpPost]
public List<MyRows> GetAllRows(string userName, string tableName)

   ...

HttpPost AND GetAllRows ?

为什么不这样做:

[Route("GetAllRows/user/table")]
public List<MyRows> GetAllRows(string userName, string tableName)

   ...

或更改为 Route("PostAllRows" 和 PostRows 我认为您确实在执行 GET 请求,因此我显示的代码应该适合您。您来自客户端的调用将是 ROUTE 中的任何内容,因此它会找到您的METHOD 与 GetAllRows,但方法本身,该名称可以是您想要的任何名称,因此只要调用者与 ROUTE 中的 URL 匹配,如果您真的需要,您可以为该方法输入 GetMyStuff。

更新:

我实际上更喜欢explicit 类型为HTTP methods 而且我更喜欢将路由参数与方法参数匹配

[HttpPost]
[Route("api/lead/vendorNumber/recordLocator")]
public IHttpActionResult GetLead(string vendorNumber, string recordLocator)
 .... 

(路由 lead 不需要匹配方法名称 GetLead 但您会希望在路由参数和方法参数上保持相同的名称,即使您可以更改顺序,例如将 recordLocator 放在 vendorNumber 之前如果路线相反 - 我不这样做,为什么让它看起来更混乱)。

奖励: 现在您也可以随时在路由中使用 regex,例如

[Route("api/utilities/vendorId:int/utilityType:regex(^(?i)(Gas)|(Electric)$)/accountType:regex(^(?i)(Residential)|(Business)$)")]
public IHttpActionResult GetUtilityList(int vendorId, string utilityType, string accountType)
    

【讨论】:

我认为Attribute Routing 也是更好的选择。 +1 这需要 API 2,但这并不总是一种选择。 同样的建议适用于 asp.net 核心(没有尝试正则表达式),但如果我做了 [Route("~the/things/thingId/subthing id/save")]/ 和 [Route("~the/things/thingId/subthingid/submit")]/【参考方案2】:

问题是您的api/MyController/GetRowsOfType/userName/tableName/rowType URL 将始终与第一个路由匹配,因此永远无法到达第二个路由。

简单修复,首先注册您的RowsByType 路由。

【讨论】:

以上是关于具有多个参数的 Web API 路由的主要内容,如果未能解决你的问题,请参考以下文章

无法使用具有多个参数的 MVC Web Api HttpPost 修饰操作

在 ASP.NET Web API 中使用多个 Get 方法进行路由

弃用单个 Web API 方法上的多个路由中的特定路由

具有不同参数的多个路由,调用相同的资源

Web API 路由 - 找到与请求匹配的多个操作

Next js中具有多个参数的动态路由