Search code examples
c#asp.netrestwebapi

REST API - How to implement multiple methods with same name but different accepted parameters type


Let's say I want to implement a User API Controller. Client needs to get users by integer ID, so I create a method GET - /api/User/{id:int}.

Then for some reason I want to implement getting a user by its name. The most obvious solution is to create GET - /api/User/{name:string} but this method will be conflicting with the previous one. Naming a method /api/UserByName/{name:string} breaks REST entity rules.

How can I deal with this problem without breaking REST rules?

Update: I just wrote the following code to create multiple routes:

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

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

This code cannot be translated by swagger and produces an error:

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

Calling a method raises another exception:

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)


Solution

  • What I did mean by using [FromQuery] is this. It would required for you to have a class with id and name

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

    Then have the route like this

    [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();
    }