首页 > 解决方案 > 添加多个 GET 动词会产生 AmbiguousMatchException 错误

问题描述

我有一个使用 .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-apiasp.net-core-webapiasp.net-core-3.1

解决方案


映射到控制器操作时,路由需要是唯一的。

在这种情况下,路由[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) {
    //...
}

参考路由到 ASP.NET Core 中的控制器操作

ASP.NET Core 中的参考路由


推荐阅读