'ASP.NET CORE, Web API: No route matches the supplied values
PLEASE NOTE: This question was asked in 2016. The original answer to this problem was to update the microsoft api versiong package. In the current days, the problem reoccurs, but for other reasons.
Original Question:
i have some problems with the routing in asp.net core (web api).
I have this Controller (simplified):
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[Controller]")]
public class DocumentController : Controller
{
[HttpGet("{guid}", Name = "GetDocument")]
public IActionResult GetByGuid(string guid)
{
var doc = DocumentDataProvider.Find(guid);
if (doc == null)
return NotFound();
return new ObjectResult(doc) {StatusCode = 200};
}
[HttpPost]
public IActionResult Create([FromBody] Document doc)
{
//... Creating Doc
// Does not work
var val = CreatedAtRoute("GetDocument", new {guid = doc.Guid.ToString("N")}, document);
// or this:
CreatedAtRoute("GetDocument", new { controller = "Document", guid = doc.Guid.ToString("N")}, document);
// neither this
var val = CreatedAtRoute("GetDocument", new { version = "1", controller = "Document", guid = doc.Guid.ToString("N")}, document);
return val;
}
}
If i call Create, the document is created and the routing object was created but i get the error "No route matches the supplied values" and get a 500 status.
I can call the GetByGuid directly, without any problems.
I couldn't find any debugging help for asp.net core (like any existing routing debugger).
I would appreciate any help!
EDIT Looks like it would be a bug from microsoft's versioning package.. if i define the fix route /api/v1/[Controller] it's working.
But that's not a solution for me.
Solution 1:[1]
ASP.net core 3
Why this problem occurs:
"As part of addressing dotnet/aspnetcore#4849, ASP.NET Core MVC
trims the suffix Async from action names by default. Starting with ASP.NET Core 3.0, this change affects both routing and link generation."
As @Chris Martinez says in this thread:
The reason for the change was not arbitrary; it addresses a different bug. If you're not affected by said bug and want to continue using the Async suffix as you had been doing.
How to solve
Re-enable it:
services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
You should now pass the createActionName parameter including the Async suffix like this:
return CreatedAtAction("PostAsync", dto)
Solution 2:[2]
I know this post is from 2017 but still i just faced the same problem and ended up here. And as it looks like you never found your mistake I'll write it here for anyone else that founds this post.
The problem is that when you call:
CreatedAtRoute("GetDocument", new { version = "1", controller = "Document", guid = doc.Guid.ToString("N")}, document);
You are telling the program to look for a "GetDocument" function that receives 3 parameters, in this case 3 strings but your actual "GetDocument" definition receives only 1 string that is your "guid":
[HttpGet("{guid}", Name = "GetDocument")]
public IActionResult GetByGuid(string guid)
{
var doc = DocumentDataProvider.Find(guid);
if (doc == null)
return NotFound();
return new ObjectResult(doc) {StatusCode = 200};
}
So for it to work you should have it like this:
CreatedAtRoute("GetDocument", new { guid = doc.Guid.ToString("N")}, document);
Another option would be to create a new get method with 3 strings and maybe you'll have to call it something different than "GetDocument".
Hope this helps the next one that comes looking for this :D
Solution 3:[3]
In my case it was a copy/paste error. The CreatedAtAction method had the wrong action name parameter. Make sure the first parameter (the actionName parameter) matches the action name (the function name). The corrected code is seen below:
Solution 4:[4]
I just used return CreatedAtAction("ActionMethodName", dto); instead until they fix that bug.
Solution 5:[5]
Another reason this error occurs is b/c when you use the CreatedAtAction to return 201, ASP.NET will add a Location header to the response with the url where the resource can be accessed. It uses the actionName to do this, so the method name needs to match a valid method on your controller. For example:
return CreatedAtAction("GetUser", new { id = user.UserId }, user);
If GetUser does not exist, the call will fail. Better practice probably to use:
return CreatedAtAction(nameof(GetUser), new { id = user.UserId }, user);
Solution 6:[6]
Just in case, if you are like me, don't like to inherit from any of the in built ControllerX base classes, then you might face this issue, if you use following statement
new CreatedAtActionResult(nameof(GetBookOf),
nameof(BooksController),
new {id = book.Id.ToString("N")},
book)
It's because second parameter in the above statement, expect us to pass the constructor name without Controller suffix.
Hence, if you change like following, then it would work just fine.
new CreatedAtActionResult(nameof(GetBookOf),
"Books",
new {id = book.Id.ToString("N")},
book)
Solution 7:[7]
I had the same symptoms but the cause was something else. Basically it doesn't like the fact that my action method ends with Async. It works when I either rename the action method from GetAsync to Get, or add [ActionName("GetAsync")] to the action.
Source: https://github.com/microsoft/aspnet-api-versioning/issues/601
Solution 8:[8]
This worked for me... https://www.josephguadagno.net/2020/07/01/no-route-matches-the-supplied-values
my get-async was...
[HttpGet("{id}", Name = nameof(GetSCxItemAsync))]
public async Task<ActionResult<SCxItem>> GetSCxItemAsync(Guid id)
but in order to get around route error I had to add the following before the function declaration...
[ActionName(nameof(GetSCxItemAsync))]
Solution 9:[9]
Instead of this:
CreatedAtRoute("GetDocument", new { version = "1", controller = "Document", guid = doc.Guid.ToString("N")}, document);
Change your return to the following:
return CreatedAtRoute("GetDocument",doc, null);
Solution 10:[10]
I'm going to stick this in here for some other poor unfortunate soul as I've spent far too long working out what I was doing wrong.
This is wrong:
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
What this does is mask the problem by returning the default route which is [controller], when what you want it to return is [controller]\{newly generated id}.
This is correct:
return CreatedAtAction(nameof(GetUser), new { id = user.UserId }, user);
However there is an edge case where this fails, this being when user.UserId is null. I think that this fails because the id parameter is required, so cannot be null, thus the route doesn't bind. It's good that it fails because if it didn't then you would be creating a junk route, but the error message is more cryptic than perhaps it could be.
In my case I was returning the Id on the input object, which was null, not the newly generated Id on the output object.
Solution 11:[11]
If your route has parameters (for example GetbookById(int id)) then you need 3 parts to the CreatedAtRoute for example:
book b = new book(); // The Created new book.
var routeValues = new { id = book.Id}; // Represents the parameter(s) to GetbookById
return CreatedAtRoute( nameof(GetbookById), routeValues, b);
More in: Created, CreatedAtAction, CreatedAtRoute Methods In ASP.NET Core Explained With Examples
Solution 12:[12]
you must give a name for a method like below and return
[HttpGet("{id}",Name = "MethodName")]
public async Task<IActionResult> MethodName(int id)
{
var baseItem = await _baseItemService.BaseItemByIdAsync(baseItemId);
return Ok(baseItem);
}
then you need return CreatedAtRoute in Post or Put Method to get Item by Id or etc such as
var (errorMessage, baseItem) = await _baseItemService.AddBaseItem(model);
if (baseItem != null) return CreatedAtRoute("MethodName", new { baseItemId = baseItem.BaseItemId }, baseItem);
return BadRequest(errorMessage );
me must give the same method name
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow

