How to handle multiple endpoints in ASP.Net Core 3 Web API properly
12,742
Solution 1
You can use route constraint
[HttpGet("{id:int}")]
public async Task<ActionResult<Fighter>> GetFighter(int id)
[HttpGet("{name}")]
public async Task<ActionResult<IEnumerable<Fighter>>> GetFighter (string name)
Solution 2
I had this problem in Core 3.0. I finally found the solution was to put a route attribute on the action - e.g. [Route("NodeInfo")]
. That fixed it
Comments
-
merkithuseyin almost 2 years
I have 2 methods to handle HTTP GET requests, first one for
int
type input and the other one forstring
type input.//GET : api/Fighters/5 [HttpGet("{id}")] public async Task<ActionResult<Fighter>> GetFighter(int id) { var fighter = await _context.Fighters.FindAsync(id); if (fighter == null) { return NotFound(); } return fighter; } // GET: api/Fighters/Alex [Route("api/Fighters/{name}")] [HttpGet("{name}")] public async Task<ActionResult<IEnumerable<Fighter>>> GetFighter (string name) { return await _context.Fighters.Where(f => f.Name == name).ToListAsync(); }
when i send HTTP GET this exception appears (in Postman):
Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches: FighterGameService.Controllers.FightersController.GetFighter (FighterGameService) FighterGameService.Controllers.FightersController.GetFighter (FighterGameService) FighterGameService.Controllers.FightersController.GetFighter (FighterGameService) FighterGameService.Controllers.FightersController.GetFighter (FighterGameService) at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ReportAmbiguity(CandidateState[] candidateState) at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ProcessFinalCandidates(HttpContext httpContext, CandidateState[] candidateState) at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.Select(HttpContext httpContext, CandidateState[] candidateState) at Microsoft.AspNetCore.Routing.Matching.DfaMatcher.MatchAsync(HttpContext httpContext) at Microsoft.AspNetCore.Routing.Matching.DataSourceDependentMatcher.MatchAsync(HttpContext httpContext) at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
GET api/fighters/1
would cause error obviously since "1
" could be eitherint
orstring
so i solved my problem by combining two methods:// GET: api/Fighters/5 // GET: api/Fighters/Alex [HttpGet("{idOrName}")] public async Task<ActionResult<IEnumerable<Fighter>>> GetFighter(string idOrName) { if (Int32.TryParse(idOrName, out int id)) { return await _context.Fighters.Where(f => f.Id == id).ToListAsync(); } else { return await _context.Fighters.Where(f => f.Name == idOrName).ToListAsync(); } }
this works however this doesn't feel right at all. What is the proper way to handle this problem?