在 ASP.NET Core Web Api 中有多个带有多个查询字符串参数的 get 方法

Posted

技术标签:

【中文标题】在 ASP.NET Core Web Api 中有多个带有多个查询字符串参数的 get 方法【英文标题】:Having multiple get-methods with multiple query string parameters in ASP.NET Core Web Api 【发布时间】:2016-08-03 08:47:36 【问题描述】:

我正在构建一个 web api,其中我有一个资源必须有 3 个 get 方法,如下所示:

    [HttpGet]
    [Route("city/streetName/streetNumber/littera")]
    public IActionResult GetByAddress([FromQuery]string city, [FromQuery]string streetName, [FromQuery]int streetNumber, [FromQuery]string littera)
    
        var model = _availabilityService.FindByAddress(city, streetName, streetNumber, littera);
        return Ok(model);
    

    [HttpGet("pointId")]
    public IActionResult GetByPointId(string pointId)
    
        var model = _availabilityService.FindByPointId(pointId);
        return Ok(model);
    

    [HttpGet]
    [Route("xCoordinate/yCoordinate")]
    public IActionResult GetByCoordinates([FromQuery]decimal xCoordinate, [FromQuery]decimal yCoordinate)
    
        var model = _availabilityService.FindByCoordinates(xCoordinate, yCoordinate);
        return Ok(model);
    

只有一个参数(pointId)的 get 方法工作正常,因为它不被视为查询字符串,而是 id。然而其余的 2 种方法似乎在 ASP.NET 中的路由器无法区分。

我真的很茫然,无法弄清楚为什么它不起作用。我能够解决的是,如果我删除其中一种方法,另一种方法可以正常工作。

关于我做错了什么有什么建议吗?

仅供参考,对应的 url:s 应该如下所示:

api/1.0/availabilities?city=Metropolis&streetName=Superstreet&streetNumber=1&littera=A

/api/1.0/availabilities?xCoordinate=34.3444&yCoordinate=66.3422

谢谢!

【问题讨论】:

当你说它不起作用时,你通过调用另外两个动作究竟得到了什么? 404? @jpgrassi:我刚刚收到 500 个内部服务器错误。我使用了调试器,发生的事情是甚至从未到达端点,所以我的结论是我的路由混乱和混乱。 :( 【参考方案1】:

首先你要混合使用 RouteParameters 和 QueryParameters。

这个:

[HttpGet]
[Route("xCoordinate/yCoordinate")]
public IActionResult GetByCoordinates([FromQuery]decimal xCoordinate, [FromQuery]decimal yCoordinate)

    var model = _availabilityService.FindByCoordinates(xCoordinate, yCoordinate);
    return Ok(model);

将控制器操作GetByCoordinates 映射到这样的路由:

/api/1.0/availabilities/34.3444/66.3422

但您还指定您期望 xCoordinateyCoordinate 与查询参数绑定。所以上面的 url 会匹配动作,但 xCoordinateyCoordinate 会绑定到它的默认值(在本例中为 0)。

所以为了得到你想要的路由,你不应该声明路由参数:

[HttpGet]
[Route("")] // <- no route parameters specified
public IActionResult GetByCoordinates([FromQuery]decimal xCoordinate, [FromQuery]decimal yCoordinate)

   // will be matched by e.g.
   // /api/1.0/availabilities?xCoordinate=34.3444&yCoordinate=66.3422

现在您想要的路线将匹配。

注意:您不能将两个动作映射到同一个路由 - 路由中间件不知道该选择哪一个。因此,从GetByAddress 中删除路由参数也会有效地将两个操作映射到同一路由:

/api/1.0/availabilities?any=number&of=query&parameters=here

因此,例如,您将不得不通过另一个路线段来区分它们。

[HttpGet]
[Route("address")] // <--
public IActionResult GetByAddress([FromQuery]string city, [FromQuery]string streetName, [FromQuery]int streetNumber, [FromQuery]string littera)

    // will be matched by e.g.
    // api/1.0/availabilities/address?city=Metropolis&streetName=Superstreet&streetNumber=1&littera=A

进一步阅读:

ModelBinding/Routing

快速提示:

appsettings.json 中将Microsft 日志级别设置为Debug(在标准Asp.Net Core WebApplication 模板中自动生成),您将在运行时在控制台输出中获得有关路由选择/错误的非常有用的信息红隼。


  "Logging": 
  "IncludeScopes": false,
  "LogLevel": 
    "Default": "Debug",
    "System": "Information",
    "Microsoft": "Debug"

或者在StartUp.csLogLevel.Debug 中设置调试记录器,您可以直接在Visual Studio 中的调试输出中获得相同的信息。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    
        // ...

        loggerFactory.AddDebug(LogLevel.Debug);

        // ...
    

【讨论】:

感谢您的精彩解释。您所描述的内容确实有道理。然而,这提出了一个新问题,它是否是一种传统的精简方式,为资源添加“路由词”以指定其含义?感谢您的回答,我已将其标记为已回答! :) @KasperP 在我看来,在设计 api 时做最适合你的事情。也就是说,特别是当您询问约定时,REST 将是您可以(尝试)遵循的约定/范式。我可能会在一个搜索操作中合并GetByAddressGetByCoordinates,因为它似乎就是这样。 REST, URI-Design 感谢您的回答。对于诸如route/session?drop 之类的语法,是否有任何实用的方法来实现查询标志,其中参数 drop 指定如果有会话,则应删除会话。还是需要独特的路线?

以上是关于在 ASP.NET Core Web Api 中有多个带有多个查询字符串参数的 get 方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使 ASP.NET Core Web API 操作异步执行?

这是从 ASP.NET Core Web API 中的 EF Core 5 获得的啥样的响应 [关闭]

IdentityServer4 基于角色的 Web API 授权与 ASP.NET Core 身份

将文件从 ASP.NET Core Web api 发布到另一个 ASP.NET Core Web api

ASP.NET Core Web Api 自动帮助页面

ASP.NET Core Web API