【发布时间】: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的任何参数。所以id和idr都是0。 -
@KingKing 修改路线并没有什么不同。 [Route("query/{cityr?}")] 仍然去 Get 而不是 GetByCity
-
看起来
query没有考虑匹配路由和查找操作方法。查询值并不总是需要相应的参数(绑定),因为操作代码可以通过查询值提供程序(像字典一样访问)轻松获取查询值。您不应该将您的 api 设计为处于这种模棱两可的选择中。在最后一种情况下,首先声明哪个方法(使用RouteAttribute)具有更高的优先级。您可以尝试切换他们的声明顺序来查看。您可以显式设置Order(在[Route]上),但这并不是真正推荐的。
标签: c# asp.net-core