路由:通过查询参数解决不明确的请求

发布于 2025-01-09 11:40:40 字数 2216 浏览 4 评论 0原文

给定下面的 RecordsController,以下请求应该是可能的,并相应地映射到端点

  1. /api/Records
  2. /api/Records/9b858599-7639-45da-acd6-a1323fb019b5
  3. /api/记录/9b858599-7639-45da-acd6-a1323fb019b5?asOf=2022-01-01
  4. /api/Records/9b858599-7639-45da-acd6-a1323fb019b5?From=2022-01-01&To=2022-03-01

映射到:

  1. GetAll(Guid id)
  2. Get(Guid id)
  3. GetAsOf(Guid id1, [FromQuery ] 字符串 asOf)
  4. GetHistory(Guid id2, [FromQuery] string from,[FromQuery] string to)
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class RecordsController : ControllerBase
    {
        private readonly ILogger<RecordsController> _logger;

        public RecordsController(ILogger<RecordsController> logger)
        {
            _logger = logger;
        }

        [HttpGet()]
        public ActionResult<IEnumerable<Record>> GetAll()
        {
            _logger.LogInformation("GetAll() was used");
            return Ok();
        }

        [HttpGet("{id:Guid}")]
        public ActionResult<Record> Get(Guid id)
        {
            _logger.LogInformation("Get() was used");
            return Ok();
        }

        [HttpGet("{id1:Guid}")]
        public ActionResult<IEnumerable<Record>> GetAsOf(Guid id1, [FromQuery] string asOf)
        {
            _logger.LogInformation("GetAsOf() was used");
            return Ok();
        }
        [HttpGet("{id2:Guid}")]
        public ActionResult<IEnumerable<Record>> GetHistory(Guid id2, [FromQuery] string from, [FromQuery] string to)
        {
            _logger.LogInformation("GetHistory() was used");
            return Ok();
        }
    }

    public class Record
    {
        public Guid Id { get; set; }
        public string Comment { get; set; } = string.Empty;
    }
}

这没有按预期工作。 上面的实现会导致 AmbigouslyMatchException。

使用IRouteTemplateProvider.Order有可能影响此行为,但随后请求 2. - 4. 将被路由到具有最低 Order 的端点。

除了将 FromQuery 更改为 FromRoute 之外,您是否看到任何可能性?

谢谢!

Given the RecordsController below, the following requests shall be possible and mapped to the endpoints accordingly

  1. /api/Records
  2. /api/Records/9b858599-7639-45da-acd6-a1323fb019b5
  3. /api/Records/9b858599-7639-45da-acd6-a1323fb019b5?asOf=2022-01-01
  4. /api/Records/9b858599-7639-45da-acd6-a1323fb019b5?From=2022-01-01&To=2022-03-01

Mapped to:

  1. GetAll(Guid id)
  2. Get(Guid id)
  3. GetAsOf(Guid id1, [FromQuery] string asOf)
  4. GetHistory(Guid id2, [FromQuery] string from, [FromQuery] string to)
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class RecordsController : ControllerBase
    {
        private readonly ILogger<RecordsController> _logger;

        public RecordsController(ILogger<RecordsController> logger)
        {
            _logger = logger;
        }

        [HttpGet()]
        public ActionResult<IEnumerable<Record>> GetAll()
        {
            _logger.LogInformation("GetAll() was used");
            return Ok();
        }

        [HttpGet("{id:Guid}")]
        public ActionResult<Record> Get(Guid id)
        {
            _logger.LogInformation("Get() was used");
            return Ok();
        }

        [HttpGet("{id1:Guid}")]
        public ActionResult<IEnumerable<Record>> GetAsOf(Guid id1, [FromQuery] string asOf)
        {
            _logger.LogInformation("GetAsOf() was used");
            return Ok();
        }
        [HttpGet("{id2:Guid}")]
        public ActionResult<IEnumerable<Record>> GetHistory(Guid id2, [FromQuery] string from, [FromQuery] string to)
        {
            _logger.LogInformation("GetHistory() was used");
            return Ok();
        }
    }

    public class Record
    {
        public Guid Id { get; set; }
        public string Comment { get; set; } = string.Empty;
    }
}

This is not working as expected.
An implementation as above leads to a AmbiguousMatchException.

Using the IRouteTemplateProvider.Order there is a possibility to influence this behavior but then the requests 2. - 4. are routed to the endpoint with the lowest Order.

Do you see any possibities apart from changing FromQuery to FromRoute?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人海汹涌 2025-01-16 11:40:40

方法 2-4 确实不明确,因为它们都是相同的端点,只是具有不同的查询参数。因此,您要么需要使它们具有不同的路由,要么可以将端点表示为具有所有可能的查询参数的单个方法,并从那里使用存在的查询参数来映射到特定的方法。

HttpGet("{id:Guid}")]
public ActionResult<Record> Get(Guid id, [FromQuery] string asOf, [FromQuery] string from, [FromQuery] string to)
{
    if (asOf != null) return GetAsOf(id, asOf);
    if (from != null && to != null) return GetHistory(id, from, to);
    return Get(id);
}

public ActionResult<Record> Get(Guid id)
{
    _logger.LogInformation("Get() was used");
    return Ok();
}

public ActionResult<IEnumerable<Record>> GetAsOf(Guid id, string asOf)
{
    _logger.LogInformation("GetAsOf() was used");
    return Ok();
}

public ActionResult<IEnumerable<Record>> GetHistory(Guid id2, [FromQuery] string from, [FromQuery] string to)
{
    _logger.LogInformation("GetHistory() was used");
    return Ok();
}

Methods 2-4 are indeed ambiguous as they all are the same endpoint, just with different query parameters. So you either need to make them have different routes, or you can express the endpoint as a single method with all the possible query parameters and from there, use which query parameters are present to map to the specific methods.

HttpGet("{id:Guid}")]
public ActionResult<Record> Get(Guid id, [FromQuery] string asOf, [FromQuery] string from, [FromQuery] string to)
{
    if (asOf != null) return GetAsOf(id, asOf);
    if (from != null && to != null) return GetHistory(id, from, to);
    return Get(id);
}

public ActionResult<Record> Get(Guid id)
{
    _logger.LogInformation("Get() was used");
    return Ok();
}

public ActionResult<IEnumerable<Record>> GetAsOf(Guid id, string asOf)
{
    _logger.LogInformation("GetAsOf() was used");
    return Ok();
}

public ActionResult<IEnumerable<Record>> GetHistory(Guid id2, [FromQuery] string from, [FromQuery] string to)
{
    _logger.LogInformation("GetHistory() was used");
    return Ok();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文