【问题标题】:How to handle multiple endpoints in ASP.Net Core 3 Web API properly如何正确处理 ASP.Net Core 3 Web API 中的多个端点
【发布时间】:2019-09-29 16:19:07
【问题描述】:

我有两种方法来处理 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 时出现此异常(在 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 显然会导致错误,因为“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();
    }

}

这行得通,但感觉根本不对。处理这个问题的正确方法是什么?

【问题讨论】:

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


    【解决方案1】:

    你可以使用route constraint

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

    【讨论】:

      【解决方案2】:

      我在 Core 3.0 中遇到过这个问题。我终于发现解决方案是在动作上放置一个路由属性 - 例如[Route("NodeInfo")]。解决了它

      【讨论】:

      • 至少当您有一个具有相同签名的端点时,这是正确的答案
      【解决方案3】:

      请按照.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}");
                  }
      
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-13
        • 2016-12-02
        • 2021-12-29
        • 2018-12-17
        • 2020-10-31
        • 1970-01-01
        • 2019-04-10
        相关资源
        最近更新 更多