【问题标题】:Web API routing with multiple parameters具有多个参数的 Web API 路由
【发布时间】: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 属性路由的回答

标签: c# asp.net-web-api asp.net-web-api-routing


【解决方案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}/subthing{id}/submit")]/
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    • 1970-01-01
    • 2019-11-22
    相关资源
    最近更新 更多