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

ASP.NET Core Web API : route by query parameter

我来自沉重的 Java/Spring 背景并试图将一些知识转移到 ASP.NET Core 6。

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

所以 HttpRequest 与 uri: /students?firstName=Kevin 可以路由到不同的控制器方法而不是 HttpRequest 与 uri: /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 */
    }
 }

我想你正在寻找这样的东西,你需要在“HttpGet”属性中指定参数

https://docs.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);
    }
}

您正在尝试使用 query params 区分 API 个调用。这不是这样做的方法。如果你想分开调用,你应该使用 path params 代替。

详细了解 ASP.NET 核心中的路由 - https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-6.0

虽然 ASP.NET 核心没有开箱即用的按查询参数过滤,但您自己提供此功能并不难。

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

Supports conditional logic to determine whether or not an associated action is valid to be selected for the given request. (Source)

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

一样简单
[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; }
}

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

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

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

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