asp.net REST API -如何实现多个具有相同名称但接受参数类型不同的方法

2ledvvac  于 2023-06-25  发布在  .NET
关注(0)|答案(3)|浏览(189)

假设我想实现一个用户API控制器。客户端需要通过整数ID获取用户,所以我创建了一个方法GET - /api/User/{id:int}
然后出于某种原因,我想实现通过用户名获取用户。最明显的解决方案是创建GET - /api/User/{name:string},但这种方法将与以前的方法相冲突。将方法命名为/api/UserByName/{name:string}违反了REST实体规则。
如何在不违反REST规则的情况下处理此问题?
upd:我刚刚写了以下代码来创建多个路由:

[HttpGet]
    public async Task<IActionResult> Get([FromQuery] int id)
    {
        return Ok();
    }
    
    [HttpGet]
    public async Task<IActionResult> Get([FromQuery] string name)
    {
        return Ok();
    }

swagger无法翻译此代码,并产生错误Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Conflicting method/path combination "GET WeatherForecast" for actions - WebApiSkeleton.API.Contro llers.WeatherForecastController.Get (WebApiSkeleton.API),WebApiSkeleton.API.Controllers.WeatherForecastController.Get (WebApiSkeleton.API). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround
调用方法会引发另一个异常:Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches: WebApiSkeleton.API.Controllers.WeatherForecastController.Get (WebApiSkeleton.API) WebApiSkeleton.API.Controllers.WeatherForecastController.Get (WebApiSkeleton.API)

shyt4zoc

shyt4zoc1#

我使用[FromQuery]的意思是。它要求你有一个带有id和name的类

public class UserFilter
{
    public int? Id { get; set; }
    public string Name { get; set; }
}

然后有这样的路线

[HttpGet]
public async Task<IActionResult> Get([FromQuery] UserFilter filter)
{
    if (filter.Id.HasValue)
    {
        // Search by id
    }
    else if (!string.IsNullOrWhiteSpace(filter.Name))
    {
        // Searh by name
    }
    return BadRequest();
}
k5ifujac

k5ifujac2#

ASP.NET核心路由在选择路由时使用优先级,通常从更特定到一般。因此,如果你有两条路由,一条带有{id:int},另一条没有任何限定符或:alpha限定符,那么如果你发送一个int,{id:int}就会被命中,否则,另一条更通用的路由也会被命中。这意味着这两条路线可以共存,并将做您想做的事情:

[HttpGet("something/{id:int}")]
public IActionResult Get1(int id)
{
    return Ok();
}

[HttpGet("something/{id}")]
public IActionResult Get2(string id)
{
    return Ok();
}

您可以测试使用postman或任何http客户端调用这两个enpoints。您遇到的错误可能与swagger无法生成文档有关,该文档如下所示:Conflicting method/path combination这与www.example.com的核心无关asp.net,而是趾高气扬。
您可以忽略从swagger中获取{id:int}的那个,因为它不太通用。您可以用途:[ApiExplorerSettings(IgnoreApi = true)]一旦你这样做了,如果你打开swagger,你会看到一个单一的端点,但如果你尝试使用int,你会遇到{id:int}端点,否则你会遇到{id}端点。

nkcskrwz

nkcskrwz3#

[HttpGet]
[Route("api/controller")]
public async Task<IHttpActionResult> Get([FromQuery]string parameter)
{
    if (!string.IsNullOrEmpty(parameter))
    {
        if (int.TryParse(parameter, out int id))
        {
            // Logic to retrieve data based on the ID asynchronously
            // Example: var data = await repository.GetDataByIdAsync(id);
            // return Ok(data);
        }
        else
        {
            // Logic to retrieve data based on the name asynchronously
            // Example: var data = await repository.GetDataByNameAsync(parameter);
            // return Ok(data);
        }
    }

    // Handle invalid or missing parameter
    return BadRequest("Invalid parameter.");
}

在此更新的示例中,GetData方法接受一个string类型的形参参数。它检查参数是否不为null或空。如果它不是空的,它会尝试使用int.TryParse()将其解析为整数。如果解析成功,它将参数视为ID,并执行逻辑以基于ID检索数据。如果解析失败,它将参数视为名称,并执行逻辑以基于名称检索数据。
样本终点:
按整数:

GET /api/controller?parameter=123

按字符串:

GET /api/controller?parameter=SOMENAME

相关问题