1

I'm porting an older API project from .NET Framework 4.7.2 to .NET 5, and I would like to keep the same API signatures as the existing project to preserve API compatibility. That's proving troublesome. (For this question, ignore that context; I'm just giving it to say why I don't want to change the URL routes as Zhi Lv has suggested.)

One of the .NET 5 project's controllers has an action with this signature:

[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)

When I attempt to access using this URL:

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

... I receive the following:

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)

That other controller action mentioned in that error has this signature:

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

If I comment out the offending, "ambiguous" match and make a new call, I receive...

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

The same error appears if I flip the experiment by commenting out the intended endpoint, GetQuestionByProcessedId, and leave only GetQuestionsForFolder.

Note that I ­can successfully access the GetQuestionsForFolder endpoint (when it's not commented out, natch) using the following URL:

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


Question

These errors seem to be in conflict. In one case, I have too many endpoints ready to serve the GET request. When I remove one of the two, I then have none.

How can I make the URL find the right controller action, and why is it seeing two and then seeing none?

To be overly clear, I am aware that I could likely merge the endpoints to resolve this issue. My question is why I have two endpoints grabbing the request and then, when one is removed, none.

ruffin
  • 16,507
  • 9
  • 88
  • 138

1 Answers1

2

The request matched multiple endpoints

To solve the above error, you could set the route constraint for each endpoint.

For example:

    [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());
    }

The result as below:

enter image description here

Besides, you can also add the action name in the route/request url, code as below:

    [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());
    }

Then the request URL like this:

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

https://localhost:44310/api/todo/getQuestionByProcessedId/2

the output as below:

enter image description here

Zhi Lv
  • 18,845
  • 1
  • 19
  • 30
  • Good heavens, yes, that's it. I misread the error when I did `[Route("{processedId:int}")]` and assumed it was `AmbiguousMatchException` when it was not -- it was a `NotImplementedException` _further down in my code_. So to fix the `AmbiguousMatchException`, you do exactly as you've shown. To ensure it then works and doesn't return an exception, one ensures that the rest of their code is error free. Thanks for kicking me back in the right direction! – ruffin Sep 22 '21 at 13:39