Resolve the issue of request matched multiple endpoints in .NET Core Web API

If there are two endpoint with same route, .NET Core Web API will throw request matched multiple endpoints error. Here is an example;

// api/menus/{menuId}/menuitems
[HttpGet("{menuId}/menuitems")]
public IActionResult GetAllMenuItemsByMenuId(int menuId)
{            
    ....
}

// api/menus/{menuId}/menuitems?userId={userId}
[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItemsByMenuAndUser(int menuId, int userId)
{
    ...
}

This is impossible because the actions are dynamically activated. The request data (such as a query string) cannot be bound until the framework knows the action signature. It can’t know the action signature until it follows the route. Therefore, we can’t make routing dependent on things the framework doesn’t even know yet.

Long and short, we need to differentiate the routes in some way: either some other static path or making the userId a route param. However, we don’t actually need separate actions here. All action params are optional by default. Therefore, we can just have:

[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItemsByMenu(int menuId, int userId)

And then we can branch on whether userId == 0 (the default). That should be fine here, because there will never be a user with an id of 0, but we may also consider making the param nullable and then branching on userId.HasValue instead, which is a bit more explicit.

We can also continue to keep the logic separate, if we prefer, by utilizing private methods. For example:

[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItems(int menuId, int userId) =>
    userId == 0 ? GetMenuItemsByMenuId(menuId) : GetMenuItemsByUserId(menuId, userId);

private IActionResult GetMenuItemsByMenuId(int menuId)
{
    ...
}

private IActionResult GetMenuItemsByUserId(int menuId, int userId)
{
    ...
}

Have fun.

Read more here.

FavoriteLoadingAdd to favorites
Spread the love

Author: Shahzad Khan

Software developer / Architect