Reputation: 1
I use OpenAPI (Swagger) in a .NET Core project and when using multiple methods that have similar get requests, I encounter "Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints." error during runtime. I look at several pages on the web and SO and tried to apply the workarounds like The request matched multiple endpoints but why?, but it does not fix the problem. Here are the API methods and route definitions that I use.
[Route("get", Name="get")]
public IEnumerable<DemoDto> Get()
{
//
}
[Route("get/{id}", Name="getById")]
public DemoDto GetById(int id)
{
//
}
[Route("get/{query}", Name="getWithPagination")]
public IEnumerable<DemoDto> GetWithPagination(DemoQuery query)
{
//
}
I use Name
property in order to fix the problem but not solved. Any idea to make changes on the routes to differentiate Get()
and GetWithPagination()
?
Upvotes: 4
Views: 18910
Reputation: 101
ASP.NET Web API 2 supports a new type of routing. Offical Doc
Route constraints let you restrict your parameters type and matched with these types (int, string, even date etc). The general syntax is "{parameter:constraint}"
[Route("users/{id:int}")]
public User GetUserById(int id) { ... }
[Route("users/{name}")]
public User GetUserByName(string name) { ... }
I tested at API;
//match : api/users/1
[HttpGet("{id:int}")]
public IActionResult GetUserById(int id){ ... }
//match : api/users/gokhan
[HttpGet("{name}")]
public IActionResult GetUserByName(string name){ ... }
Upvotes: 0
Reputation: 25370
[Route("get/{query}", Name="getWithPagination")]
This doesn't make sense. DemoQuery
is an object, it can't be represented by a single part of a url. You can tell the ModelBinder to build your object from multiple query parameters, though.
The routing engine is getting this route confused with the [Route("get/{id}", Name="getById")]
route. They both appear to match get/blah
.
In addition to fixing your DemoQuery
route, try adding a route constraint on the id
route -
[Route("get/{id:int}", Name="getById")]
to better help the engine.
To get DemoQuery
to work, assume it looks something like:
public class DemoQuery
{
public string Name { get; set; }
public int Value { get; set; }
}
Then change your action to
[Route("getPaged/{query}", Name="getWithPagination")]
public IEnumerable<DemoDto> GetWithPagination([FromQuery] DemoQuery query)
and call then endpoint like /getPaged?name=test&value=123
. And the ModelBinder should build your object for you.
Upvotes: 5
Reputation: 1317
You have two endpoints with equals routes: get/{id} and get/{query}.
If you write in browser line: get/123, the system can't understand what route to use, because they have the same pattern.
You need to distinguish them and I suggest you use restful style for routes, like: item/{id}, items?{your query}
Upvotes: 5