【问题标题】:ASP.Net Web Api Core - Route to action based on query string parameterASP.Net Web Api Core - 基于查询字符串参数的操作路由
【发布时间】:2020-04-09 14:32:59
【问题描述】:

我有一个带有两个动作的控制器。每个操作都采用一个 GUID 参数。我的请求 URL 如下所示: http://baseURL/api/v1.0/loadfactors/search?cedentId=5FF7165C-7575-EA11-AA4D-949554C02DE1

这就是我的动作的样子:

    [HttpGet("search")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<List<LoadFactorResource>> GetByLobSettingsId([FromQuery]Guid lobSettingsId)
    {
        return await _service.GetByLobSettingsId(lobSettingsId);
    }

    [HttpGet,Route("search")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<List<LoadFactorResource>> GetByAccountId([FromQuery]Guid cedentId)
    {
        return await _service.GetByCedentId(cedentId);
    }

现在,当我提出请求时,这是我得到的错误:

处理请求时发生未处理的异常。 AmbiguousMatchException:请求匹配多个端点。匹配:

LoadFactorsController.GetByLobSettingsId (Api) LoadFactorsController.GetByAccountId (Api)

它似乎正在查找多个操作,而不是根据查询参数识别操作。如何根据参数进行匹配?

谢谢。

【问题讨论】:

  • 方法签名是相同的(相同的路由,相同的 GUID 参数),因此没有任何区别。默认情况下,不考虑查询参数的名称。在这个类似的问题中尝试 IActionConstraint 响应:stackoverflow.com/questions/46477959/…
  • 你能把你的 api 改成 [HttpGet("search/LobSettingsId/{lobSettingsId:Guid}")] 和 [HttpGet("search/AccountId/{accountId:Guid}")] 那么它是明确每个人做了什么并且应该避免错误
  • @Rosco 不,我不能。我想了想,但是服务已经被客户端消费了,我只需要添加另一个查询字符串参数。
  • @BryanLewis 谢谢你成功了!

标签: asp.net-core asp.net-web-api


【解决方案1】:

处理请求时发生未处理的异常。 AmbiguousMatchException:请求匹配多个端点。

因为错误表明请求匹配了多个动作,导致歧义。

要修复它并满足您的要求,您可以尝试以下方法:

方法一: 将这两个动作合并为一个动作,动态检查客户端传递的查询字符串值。

[HttpGet("search")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<List<LoadFactorResource>> GetByLobSettingsId([FromQuery]Guid lobSettingsId, [FromQuery]Guid cedentId)
{
    if (lobSettingsId != Guid.Empty)
    {
        return await _service.GetByLobSettingsId(lobSettingsId);
    }

    return await _service.GetByCedentId(cedentId);
}

方法 2: 实现自定义 ActionMethodSelectorAttribute 以根据传递的查询字符串启用或禁用给定请求的操作,如下所示。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CheckQueryStingAttribute : ActionMethodSelectorAttribute
{
    public string QueryStingName { get; set; }
    public bool CanPass { get; set; }
    public CheckQueryStingAttribute(string qname, bool canpass)
    {
        QueryStingName = qname;
        CanPass = canpass;
    }

    public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
    {
        StringValues value;

        routeContext.HttpContext.Request.Query.TryGetValue(QueryStingName, out value);

        if (CanPass)
        {
            return !StringValues.IsNullOrEmpty(value);
        }

        return StringValues.IsNullOrEmpty(value);
    }
}

将其应用于操作

[HttpGet("search")]
[CheckQueryStingAttribute("lobSettingsId",true)]
[CheckQueryStingAttribute("cedentId", false)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<List<LoadFactorResource>> GetByLobSettingsId([FromQuery]Guid lobSettingsId)
{  
    return await _service.GetByCedentId(cedentId);                
}

[HttpGet, Route("search")]
[CheckQueryStingAttribute("lobSettingsId", false)]
[CheckQueryStingAttribute("cedentId", true)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<List<LoadFactorResource>> GetByAccountId([FromQuery]Guid cedentId)
{
    return await _service.GetByCedentId(cedentId);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 2014-05-29
    • 2017-11-20
    • 1970-01-01
    • 2023-01-27
    相关资源
    最近更新 更多