【问题标题】:Controller action throws AmbiguousMatchException at first, then NotImplementedException when one [sic] is removed控制器操作首先抛出 AmbiguousMatchException,然后在删除一个 [sic] 时抛出 NotImplementedException
【发布时间】:2021-09-21 22:09:57
【问题描述】:

我正在将一个较旧的 API 项目从 .NET Framework 4.7.2 移植到 .NET 5,并且我希望保留与现有项目相同的 API 签名以保持 API 兼容性。事实证明这很麻烦。 (对于这个问题,请忽略上下文;我只是说为什么我不想更改 URL 路由 as Zhi Lv has suggested。)

.NET 5 项目的一个控制器有一个带有这个签名的动作:

[HttpGet]
[Route("{processedId}")] 
// I had also tried [Route("{processedId:int}")] -- EDIT: but missed that there was a different exception when I did. ????
public async Task<TypedActionResult<Question>> GetQuestionByProcessedId(int processedId)

当我尝试使用此 URL 访问时:

https://localhost:12345/api/questions/2

...我收到以下信息:

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException:
The request matched multiple endpoints. Matches: 

My.Namespace.Api.Controllers.MyController.GetQuestionsForFolder (QuestionBuilder.Api)
My.Namespace.Api.Controllers.MyController.GetQuestionByProcessedId (QuestionBuilder.Api)

该错误中提到的其他控制器操作具有此签名:

[HttpGet]
[Route("{folderId=folderId:Guid}")]
public async Task<TypedActionResult<IEnumerable<Question>>> GetQuestionsForFolder(Guid folderId)

如果我注释掉有问题的“模棱两可”匹配并拨打新电话,我会收到...

System.NotImplementedException: The method or operation is not implemented.

如果我通过注释掉预期的端点GetQuestionByProcessedId 并仅留下GetQuestionsForFolder 来翻转实验,则会出现同样的错误。

请注意,我可以使用以下 URL 成功访问 GetQuestionsForFolder 端点(当它没有被注释掉时,natch):

https://localhost:12345/api/questions/?folderId=87654321-1234-1234-1234-123456789012


问题

这些错误似乎相互冲突。在一种情况下,我有 太多 端点准备好为 GET 请求提供服务。当我删除两者中的一个时,我 没有

如何使 URL 找到正确的控制器操作,为什么它看到两个然后没有看到?

说得太清楚了,我知道我很可能merge the endpoints 来解决这个问题。我的问题是为什么我有两个端点抓取请求,然后,当一个被删除时,没有一个。

【问题讨论】:

    标签: asp.net-core-webapi


    【解决方案1】:

    请求匹配多个端点

    要解决上述错误,您可以为每个端点设置route constraint

    例如:

        [HttpGet]
        [Route("{processedId:int}")] // the parameter is int type, allow the request with int parameter
        public async Task<IActionResult> GetQuestionByProcessedId(int processedId)
        {
            return Ok("value: " + processedId.ToString());
        }
    
        [HttpGet]
        [Route("{folderId=folderId:Guid}")] //the parameter is guid type, allow the request with guid parameter
        public async Task<IActionResult> GetQuestionsForFolder(Guid folderId)
        {
            return Ok("value: " + folderId.ToString());
        }
    

    结果如下:

    另外,你还可以在路由/请求的url中添加动作名称,代码如下:

        [HttpGet]
        [Route("getQuestionByProcessedId/{processedId}")] // the parameter is int type
        public async Task<IActionResult> GetQuestionByProcessedId(int processedId)
        {
            return Ok("value: " + processedId.ToString());
        }
    
        [HttpGet]
        [Route("getQuestionsForFolder/{folderId=folderId:Guid}")] //the paramer is guid type
        public async Task<IActionResult> GetQuestionsForFolder(Guid folderId)
        {
            return Ok("value: " + folderId.ToString());
        }
    

    那么请求的URL是这样的:

    https://localhost:44310/api/todo/getQuestionsForFolder/87654321-1234-1234-1234-123456789012
    
    https://localhost:44310/api/todo/getQuestionByProcessedId/2
    

    输出如下:

    【讨论】:

    • 天哪,是的,就是这样。我在执行[Route("{processedId:int}")] 时误读了错误,并认为它不是AmbiguousMatchException - 它是NotImplementedException 在我的代码中进一步向下。所以要修复AmbiguousMatchException,你完全按照你展示的那样做。为了确保它可以正常工作并且不返回异常,请确保其其余代码没有错误。 ? 谢谢你把我踢回正确的方向!
    猜你喜欢
    • 2016-05-26
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    相关资源
    最近更新 更多