The request matched multiple endpoints in ASP.NET Core

By FoxLearn 3/7/2025 4:34:00 AM   94
When you send a request to an endpoint, you might encounter the following error response:
500 - Internal Server Error

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches: 

Controllers.ProductController.GetByCategory
Controllers.ProductController.GetByProductName

If you're using Swagger, the UI may show a generic error: "Failed to load API definition … response status is 500." In Visual Studio, you can find the detailed error in the ASP.NET Core Web Server output: SwaggerGeneratorException: Conflicting method/path combination.

This error occurs when multiple controller methods have the same HTTP method and path combination, even if the path parameters are different. The framework can't determine which controller method to call, leading to the AmbiguousMatchException.

For example, you might have the following ambiguous controller methods:

[HttpGet("{category}")]
public IEnumerable<Product> GetByCategory(string category)
{
    // Return products for the specified category
}

[HttpGet("{productName}")]
public Product GetByProductName(string productName)
{
    // Return product by name
}

To resolve this issue, you need to disambiguate the paths. There are two main options:

Option 1: Use Route Constraints

You can specify the type of the path parameters using route constraints to make it clear which controller method should be invoked.

[HttpGet("{category:alpha}")]
public IEnumerable<Product> GetByCategory(string category)
{
    // Return products for the specified category
}

[HttpGet("{productName:alpha}")]
public Product GetByProductName(string productName)
{
    // Return product by name
}

Here’s how this disambiguates the request:

  • If the path parameter is alphabetic (category), the route will match GetByCategory(string category).
    • Example: GET /products/electronics routes to GetByCategory("electronics").
  • If the path parameter is also alphabetic (productName), the route will match GetByProductName(string productName).
    • Example: GET /products/phone routes to GetByProductName("phone").

You can also explore other route constraints available in ASP.NET Core for more specific matching, such as {category:int} for integers or {id:guid} for GUIDs.

Option 2: Change the Paths to Be Different

Alternatively, you can make the paths distinct by changing the route for each method.

Consider this setup, where two methods conflict with the same HTTP method and path (GET /products):

[HttpGet]
public IEnumerable<Product> GetAll()
{
    // Get all products
}

[HttpGet]
public Product GetWithQuery([FromQuery]string productName)
{
    // Get product by name
}

Both methods map to GET /products, so you need to change the paths to disambiguate them:

[HttpGet("all")]
public IEnumerable<Product> GetAll()
{
    // Get all products
}

[HttpGet("search")]
public Product GetWithQuery([FromQuery]string productName)
{
    // Get product by name
}

Now, these two methods will handle the following requests:

  • GET /products/all – Calls GetAll().
  • GET /products/search?productName=tablet – Calls GetWithQuery("tablet").

Another option is to combine the methods into one and make the query string parameter optional, allowing flexibility in handling both cases in a single method.