.net core 3.1 web api 中的多个 get 方法

Nis*_*ava 5 .net api .net-core asp.net-core

我正在尝试使用三个 get 方法创建一个非常基本的控制器以下是它们的三个 uri

  1. GET /movies - 获取所有电影。
  2. GET /movies?name={name}` - 查找与指定名称匹配的所有电影
  3. Get /Movies/{Id} - 按 ID 查找电影

我的控制器代码如下

[Route("api/[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
    private readonly IMoviesService moviesService;

    public MoviesController(IMoviesService moviesService)
    {
        this.moviesService = moviesService;
    }
    
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var result = await moviesService.GetMoviesAsync();
        return Ok(result);
    }
    
    [HttpGet]
    public async Task<IActionResult> GetByName([FromQuery(Name = "name")] string name)
    {
        var result = await moviesService.GetMoviesByNameAsync(name);
        return Ok(result);
    }

    [HttpGet("{Id}", Name = "GetById")]
    public async Task<IActionResult> GetById(Guid Id)
    {
        var result = await moviesService.GetMovieById(Id);
        return Ok(result);
    }       

}
Run Code Online (Sandbox Code Playgroud)

当我通过发送请求到GetByIdapi/movies/31234567-89ab-cdef-0123-456789abcdef那么它的工作原理,但对于api/moviesapi/movies?name=Test我得到以下错误

The request matched multiple endpoints. Matches: MoviesController.Get and MoviessController.GetByName

任何人都可以建议我考虑到最佳实践,在 web api .net core 3.1 中实现这种场景的最佳方法是什么?

Yiy*_*You 8

你最好把你的网址改成api/Movies/GetByName/{Id}, api/Movies/GetById/{Name}

然后:

  1. GET /movies - 获取所有电影。
  2. GET /movies/GetByName/{name}` - 查找与指定名称匹配的所有电影
  3. Get /Movies/GetById/{Id} - 按 ID 查找电影

添加其他动作时,您也可以为路由添加动作名称,它可以帮助您避免 The request matched multiple endpoints.

这是一个演示:

        [HttpGet]
        public async Task<IActionResult> Get()
        {
            return Ok();
        }

        [HttpGet("GetByName/{name}")]
        public async Task<IActionResult> GetByName(string name)
        {
            return Ok();
        }

        [HttpGet("GetById/{Id}")]
        public async Task<IActionResult> GetById(Guid Id)
        {
            return Ok();
        } 
Run Code Online (Sandbox Code Playgroud)

结果: 在此处输入图片说明


Mul*_*ion 4

您的GetGetByNameactions 没有为它们提供属性路由,并且都与“api/Movies”匹配。为了解决这个问题,您还需要向至少其中一个操作添加路由模板。

一个可能的解决方案是:

[HttpGet]
public async Task<IActionResult> Get()
{
    var result = await moviesService.GetMoviesAsync();
    return Ok(result);
}

[HttpGet]
[Route("{name}")]
public async Task<IActionResult> GetByName([FromRoute] string name)
{
    var result = await moviesService.GetMoviesByNameAsync(name);
    return Ok(result);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这里具有特定名称的电影的 url 不再是/movies?name={name},而是/movies/{name}

如果您绝对希望保留 URL /movies?name={name}您可以将GetGetByName操作合并到一个接受查询字符串参数的操作中name,并根据其值执行您的逻辑。

  • 当使用`/movies/xxxx`时,它会得到`请求匹配多个端点。匹配:WebAPI.Controllers.MoviesController.GetById (WebAPI) WebAPI.Controllers.MoviesController.GetByName (WebAPI)` (2认同)