Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The request matched multiple endpoints on .NET Core

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()?

like image 543
Jack Avatar asked Sep 18 '25 03:09

Jack


2 Answers

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}

like image 190
Yaroslav Bres Avatar answered Sep 19 '25 17:09

Yaroslav Bres


[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.

like image 28
Jonesopolis Avatar answered Sep 19 '25 17:09

Jonesopolis