ASP.NET Core Web API:通过查询参数路由

Kev*_*sox 6 c# routes asp.net-core-webapi asp.net-core-6.0

我拥有深厚的 Java/Spring 背景,并试图将一些知识转移到 ASP.NET Core 6。

在 Spring 上RestController,我能够根据查询参数的存在来路由请求。

HttpRequest因此,带有 uri: 的a/students?firstName=Kevin可以路由到与HttpRequest带有 uri: 的a 不同的控制器方法/students

在 ASP.NET Core 6 中,在完成一些示例并阅读 Web API 文档后,我无法确定是否可以实现同等功能。

这是我想要实现的目标,是否可以使用两种方法和路由配置来根据查询参数识别要调用哪个控制器方法?

 [ApiController]
 [Route("Students")]
 public class StudentHomeProfileController : ControllerBase
 {
    [HttpGet] //Route here when no parameters provided
    public async Task<ActionResult<IEnumerable<Student>>> GetStudentAsync()
    {
        /* Code omitted */
    }

    [HttpGet] //Route here when firstName query param provided
    public async Task<ActionResult<IEnumerable<Student>>> SearchStudentAsync([FromQuery] string firstName)
    {
        /* Code omitted */
    }
 }
Run Code Online (Sandbox Code Playgroud)

Pau*_*her 14

虽然按查询参数进行过滤并不是随 ASP.NET Core 一起提供的,但您自己提供此功能并不难。

在可扩展性方面,ASP.NET 拥有一些超能力,其中之一就是IActionConstraint

支持条件逻辑以确定为给定请求选择的关联操作是否有效。(来源

创建注释来过滤查询参数就像

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class QueryParameterConstraintAttribute : Attribute, IActionConstraint
{
    private readonly string _parameterName;

    public QueryParameterConstraintAttribute(string parameterName)
    {
        this._parameterName = parameterName;
    }

    public bool Accept(ActionConstraintContext context)
    {
        return context.RouteContext.HttpContext.Request.Query.Keys.Contains(this._parameterName);
    }

    public int Order { get; }
}
Run Code Online (Sandbox Code Playgroud)

剩下的就是用该约束注释你的控制器方法

[HttpGet] //Route here when firstName query param provided
[QueryParameterConstraint("firstName")]
public async Task<ActionResult<IEnumerable<Student>>> SearchStudentAsync([FromQuery] string firstName)
{
    /* Code omitted */
}
Run Code Online (Sandbox Code Playgroud)

在快速测试中,我能够确认它似乎按预期工作,即使您为不同的查询参数添加多个这些属性(如果所有条件匹配,则调用路由)。

(请注意,这是使用 .NET Core 2.1 进行测试的。无论如何,它应该与 .NET 6 几乎相同)

  • 我知道有一个公认的答案,但我仍然想提供该问题的解决方案,以防其他人正在寻找。 (2认同)

小智 5

我认为您正在寻找类似的东西,您需要在“ HttpGet ”属性中指定参数

https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-6.0#attribute-routing-with-http-verb-attributes

[Route("api/[controller]")]
[ApiController]
public class Test2Controller : ControllerBase
{
    [HttpGet]   // GET /api/test2
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int/{id:int}")] // GET /api/test2/int/3
    public IActionResult GetIntProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
    public IActionResult GetInt2Product(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ran*_*ner 3

您正在尝试使用 来区分 API 调用query params。这不是这样做的方法。如果你想分隔调用,你可能应该使用path params

阅读有关ASP.NET Core 中的路由的更多信息- https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-6.0