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

but5z9lq  于 2023-10-21  发布在  .NET
关注(0)|答案(6)|浏览(183)

我试图创建一个非常基本的控制器,其中有三个get方法,下面是它们的三个uri

  1. GET /movies -获取所有电影。
  2. GET /电影?name={name}` -查找与指定名称匹配的所有电影
    1.获取/电影/{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);
    }       

}

当我通过api/movies/31234567-89ab-cdef-0123-456789abcdef发送请求到GetById时,它可以工作,但对于api/moviesapi/movies?name=Test,我得到以下错误:
请求匹配多个端点。匹配项:MoviesController.Get和MoviesController.GetByName
任何人都可以请建议我什么是最好的方式来实现这种情况下在web API .net核心3.1考虑最好的插件?

vxf3dgd4

vxf3dgd41#

你最好把你的URL改成这样:api/movies/getByName/{name}api/movies/getById/{id}
然后又道:
1.获取/movies-获取所有电影

  1. GET /movies/getByName/{name}-查找与指定名称匹配的所有电影
  2. GET /movies/getById/{id}-按ID查找电影
    在添加其他操作时,您还可以将操作名称添加到路由中,这将帮助您避免The request matched multiple endpoints.
    下面是一个demo:
[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();
}

结果:x1c 0d1x

5ssjco0h

5ssjco0h2#

您的GetGetByName操作没有为其提供属性route,并且都匹配到“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);
}

请注意,在这里,具有特定名称的电影的url不再是 /movies?name={name},但是 /movies/{name}
如果您绝对希望保留URL /movies?name={name} 您可以将GetGetByName操作合并到一个接受查询字符串参数name并根据其值执行逻辑的单个操作中。

sd2nnvve

sd2nnvve3#

@Nishant,你几乎是好的,有一些小的变化。下面是解决方案。注解内联在代码中。

[Route("api/[controller]")]
[ApiController]
public class MoviesController : ControllerBase
{
    //GET /movies - gets all movies.
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        return Ok();
    }

    //GET /movies/name={name}` - finds all movies matching the specified name
    [HttpGet("{name}")]  //added the route
    public async Task<IActionResult> GetByName(string name) // modified the input parameter
    {
        return Ok();
    }

    //Get /Movies/{Id} - Find movie By Id
    [HttpGet("{Id:guid}", Name = "GetById")] //added the input type
    public async Task<IActionResult> GetById(Guid Id)
    {
        return Ok();
    }

}

请让我知道如果这有帮助。

4si2a6ki

4si2a6ki4#

你可以有多个方法,请记住,在控制器的开始,你初始化了调用控制器方法的方式,就像这样:

[Route("api/[controller]")]

.每个操作或方法必须指定[action]和名称

[Route("[action]", Name = "GetPersona")]
    [HttpGet]
    public async Task<IActionResult> GetPersona(int Id)
    {
        bool ok = false;
        string mensaje = "Sin Datos";
        var data = await Task.Run(() => _repositoryPersonas.GetPersona(Id));
        if (data != null)
        {
            mensaje = "ok";
            ok = true;
        }
        return Ok(new { data, ok, mensaje });
    }

    [Route("[action]", Name = "ObtenerPersonas")]
    public async Task<IActionResult> ObtenerPersonas(int Ids)
    {
        bool ok = false;
        string mensaje = "Sin Datos";
        var data = await Task.Run(() => _repositoryPersonas.GetPersona(Ids));
        if (data != null)
        {
            mensaje = "ok";
            ok = true;
        }
        return Ok(new { data, ok, mensaje });
    }

route1 https://localhost:44376/api/Personas/GetPersona?ID=1 route2 https://localhost:44376/api/Personas/ObtenerPersonas?Id=1

ua4mk5z4

ua4mk5z45#

我用这个

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

u4dcyp6a6#

借鉴从'Yiyi You'接受的答案,我会根据accepted answer (and others) to this question做轻微的修改。使用连字符将使你的网址更容易被搜索引擎“抓取”,如果它是一个公共的API。

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

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

[HttpGet("get-by-id/{id}")]
public async Task<IActionResult> GetById(Guid Id)
{
    return Ok();
}

相关问题