【问题标题】:Route based attributes taking the incorrect method when data constraints are applied应用数据约束时,基于路由的属性采用不正确的方法
【发布时间】:2023-03-15 15:44:01
【问题描述】:

我有以下 API 控制器类。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;

namespace Core31Test.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class DataController : ControllerBase
    {
        [HttpGet]
        [Route("query/{idr:int?}")]
        public string Get(int idr, [FromQuery] int id)
        {
            var idx = id == 0 ? idr : id;

            return $"Value: {idx}";
        }

        [HttpGet]
        [Route("query/{cityr}")]
        public string GetByCity(string cityr, [FromQuery] string city)
        {
            var cityx = string.IsNullOrEmpty(city) ? cityr : city;

            return cityx;
        }
    }
}

当我尝试通过 id 查询时,基于路由的路径和查询字符串都有效。当我尝试按城市查询时,只有基于路线的路径有效。查询字符串路径最终采用了不正确的路径。

例如:

http://localhost:51123/data/query/1
结果:值:1

http://localhost:51123/data/query?id=1
结果:值:1

http://localhost:51123/data/query/mycity
结果:我的城市

http://localhost:51123/data/query?city=acity
结果:值:0

在最后一种情况下,选择了错误的路线。为什么会发生这种情况,我该如何解决?

编辑 1

如果我将 GetByCity 方法的路线修改为下面给出的路线,则 Get 方法仍处于选中状态。在这种情况下,两种方法都有一个可选的路由参数和一个查询字符串。由于 Get 路由指定输入是一个整数,我不明白为什么 GetByCity 方法会去那个。我想知道的是如何做到这一点。

[Route("query/{cityr?}")]

【问题讨论】:

  • 它选择了正确的路径,而不是你假设的错误。 {cityr} 部分不是可选的。因此,当您发送http://localhost:51123/data/query?city=acity 时,{cityr} 部分丢失,这意味着它无法匹配方法GetByCity。相反,它匹配路由query/{idr:int?},在最后一种情况下缺少idr,查询?city 未绑定到方法Get 的任何参数。所以ididr 都是0
  • @KingKing 修改路线并没有什么不同。 [Route("query/{cityr?}")] 仍然去 Get 而不是 GetByCity
  • 看起来query 没有考虑匹配路由和查找操作方法。查询值并不总是需要相应的参数(绑定),因为操作代码可以通过查询值提供程序(像字典一样访问)轻松获取查询值。您不应该将您的 api 设计为处于这种模棱两可的选择中。在最后一种情况下,首先声明哪个方法(使用RouteAttribute)具有更高的优先级。您可以尝试切换他们的声明顺序来查看。您可以显式设置Order(在[Route] 上),但这并不是真正推荐的。

标签: c# asp.net-core


【解决方案1】:

在最后一种情况下,选择了错误的路线。为什么会发生这种情况,我该如何解决?

不,不是。正在选择正确且预期的路线。让我们仔细看看:

  • 路由是query?city=acity
  • 可用的操作有:
    • query/ + 可选的 int 参数 (query/{idr:int?})
    • query/ + 必需的字符串参数("query/{cityr}"

如果您考虑一下,query/ 不满足 query/ + 必需的字符串参数,因为没有给出 cityr 的值,所以正确的路线是 idr 重载,因为该参数是可选的。

【讨论】:

  • 修改 GetByCity 的路线没有任何区别。换句话说 [Route("query/{cityr?}")] 仍然会使用不正确的方法
猜你喜欢
  • 1970-01-01
  • 2015-08-11
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多