【问题标题】:Adding Multiple GET verbs gives an error of AmbiguousMatchException添加多个 GET 动词会产生 AmbiguousMatchException 错误
【发布时间】:2020-04-20 06:19:54
【问题描述】:

我有一个使用 .NET core 3.1 的 WebApi。我不确定这是否不是最佳实践,或者是否有其他方法可以做到这一点。但是,我有一个包含 3 个 get 动词的 WebApi。
1. 全部搞定。
2. 按 ID 获取。
3. 通过搜索字符串获取。

如果我只有 2 个,get all 并按 id 获得,但一旦我有 3 个,按字符串获得,我得到一个错误。然后当我大摇大摆地去测试时,我得到了,

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: 请求匹配多个端点。匹配:

代码:

[ApiController]
[Route("api/v1/[controller]")]
public class ProfessionalLocalController : ControllerBase
{
    private IUnitOfWork _unitOfWork;
    private readonly IMapper _mapper;

    public ProfessionalLocalController(IUnitOfWork unitOfWork, IMapper mapper)
    {
        _unitOfWork = unitOfWork;
        _mapper = mapper;
    }

    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var profLocals = await _unitOfWork.ProfessionalLocalUsers.GetAllAsync();
        return Ok(_mapper.Map<IEnumerable<ProfessionalLocalDto>>(profLocals));
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
        var localUser = await _unitOfWork.ProfessionalLocalUsers.GetAsync(id);
        if (localUser == null)
        {
            return NotFound();
        }

        return Ok(_mapper.Map<ProfessionalLocalDto>(localUser));
    }

    [HttpGet("{searchText}", Name = "Search")]
    public async Task<IActionResult> Get(string searchText)
    {
        var localUsers = await _unitOfWork.ProfessionalLocalUsers.FindAsync(temp => temp.UserID.ToString().Contains(searchText));

        return Ok(_mapper.Map<IEnumerable<ProfessionalLocalDto>>(localUsers));
    }
}

【问题讨论】:

    标签: c# asp.net-web-api asp.net-core-webapi asp.net-core-3.1


    【解决方案1】:

    您可以尝试如下更改:

    [HttpGet]
    [Route("users")]
    public async Task<IActionResult> Get()
    {
        var profLocals = await _unitOfWork.ProfessionalLocalUsers.GetAllAsync();
        return Ok(_mapper.Map<IEnumerable<ProfessionalLocalDto>>(profLocals));
    }
    
    [HttpGet("{id}")]
    [Route("users/{id}")]
    public async Task<IActionResult> Get(int id)
    {
        var localUser = await _unitOfWork.ProfessionalLocalUsers.GetAsync(id);
        if (localUser == null)
        {
            return NotFound();
        }
    
        return Ok(_mapper.Map<ProfessionalLocalDto>(localUser));
    }
    
    [HttpGet("{searchText}", Name = "Search")]
    [Route("usersbytext/{id}")]
    public async Task<IActionResult> Get(string searchText)
    {
        var localUsers = await _unitOfWork.ProfessionalLocalUsers.FindAsync(temp => temp.UserID.ToString().Contains(searchText));
    
        return Ok(_mapper.Map<IEnumerable<ProfessionalLocalDto>>(localUsers));
    }
    

    为第三个添加自定义路由。 默认路由无法区分 [Route("users/{id}")] 和 [Route("users/{id}")] 使其模棱两可。

    【讨论】:

    • 使用[HttpGet(&lt;something&gt;)] 将设置&lt;something&gt; 作为路由,就像[Route(&lt;something&gt;)] 一样。不建议使用both HttpGetRoute 来声明路由。
    【解决方案2】:

    映射到控制器动作时,路由必须是唯一的。

    在这种情况下,路由 [HttpGet("{id}")][HttpGet("{searchText}", Name = "Search")] 发生冲突,因为它们都映射到同一个 URI。

    api/v1/ProfessionalLocal/{some value here}
    

    如果您想保持与以前相同的 URI,并允许两个操作不同,请使用路由约束。

    //GET api/v1/ProfessionalLocal/1234
    [HttpGet("{id:int}")] //<-- note the constraint on the id
    public async Task<IActionResult> Get(int id) {
        //...
    }
    

    这样只有在提供有效值时才会调用上述内容。本例为整数

    并考虑将搜索的路径模板更改为更能描述其实际作用。

    //GET api/v1/ProfessionalLocal/search/{search text here}
    [HttpGet("search/{searchText}", Name = "Search")]
    public async Task<IActionResult> Get(string searchText) {
        //...
    }
    

    参考Routing to controller actions in ASP.NET Core

    参考Routing in ASP.NET Core

    【讨论】:

      【解决方案3】:

      我最近遇到了类似的问题。我的解决方案是对 GetAllSearch 使用相同的方法。我所做的是:

      检查查询参数,如果查询参数可用,则返回搜索结果,否则返回全部。请参考下面的sn-p。

          [HttpGet]
          public async Task<IActionResult> Get([FromQuery]string search)
          {
            if(!String.IsNullOrEmpty(search)) 
               // return search result
            //return all
          }
      

      【讨论】:

        猜你喜欢
        • 2020-02-13
        • 2017-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多