如何正确处理ASP.Net Core 3 Web API中的多个终结点

时间:2019-09-29 16:19:07

标签: asp.net-core asp.net-core-webapi asp.net-core-3.0

我有2种方法来处理HTTP GET请求,第一种用于int类型的输入,另一种用于string类型的输入。

//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();
}

当我发送HTTP GET时,出现此异常(在邮递员中):

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显然会导致错误,因为“ 1可以是intstring,所以我通过组合两种方法解决了我的问题:

// 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();
    }

}

这有效,但是感觉根本不对。解决此问题的正确方法是什么?

3 个答案:

答案 0 :(得分:0)

您可以使用route constraint

[HttpGet("{id:int}")]
public async Task<ActionResult<Fighter>> GetFighter(int id) 

[HttpGet("{name}")]
public async Task<ActionResult<IEnumerable<Fighter>>> GetFighter (string name)

答案 1 :(得分:0)

我在Core 3.0中遇到了这个问题。我最终发现解决方案是在操作上放置一个route属性-例如[Route(“ NodeInfo”))。修好了

答案 2 :(得分:0)

请遵循.Net Core 3.1或更高版本的解决方案:使用[Route(“ RouteName”)]

[HttpPost]
        [Route("CreateUserRole")]
       // [Authorize(Roles = "admin")]
        [ProducesResponseType(StatusCodes.Status201Created)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        public async Task<IActionResult> CreateUserRole([FromBody] AssignUserRole assignUserRole)
        {
            try
            {
                _logger.LogInfo("Attempted submission attempted");

                if (assignUserRole == null)
                {
                    _logger.LogWarn("Empty request submitted");
                    return BadRequest(ModelState);
                }
                if (!ModelState.IsValid)
                {
                    _logger.LogWarn("User data was incomplete");
                    return BadRequest(ModelState);
                }
                var User = _Mapper.Map<Users>(assignUserRole);
                _UserRoleRepository.AssignRoleUser(assignUserRole);
                _logger.LogInfo("User Role created");
                Audit_logs audit = new Audit_logs()
                {
                    uid = User.id,
                    action = "Create User Role",
                    log = $"{assignUserRole.rolename} Role has created",
                    datetime = DateTime.Now
                };
                await _audit_Logs.Create(audit);
                return Created("Create User Role", new { assignUserRole });
            }
            catch (Exception ex)
            {
                return InternalError($"{ex.Message}-{ex.InnerException}");
            }

        }