简体   繁体   中英

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.<\/strong> In the current days, the problem reoccurs, but for other reasons.<\/strong>


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

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

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."

See more: https://docs.microsoft.com/en-us/dotnet/core/compatibility/aspnetcore#mvc-async-suffix-trimmed-from-controller-action-names

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)

I'll answer my own question: It was really a bug in the versioning package of microsoft and it's gonna be fixed soon.

https://github.com/Microsoft/aspnet-api-versioning/issues/18

I just used return CreatedAtAction("ActionMethodName", dto); instead until they fix that bug.

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

dev guide apidocs

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

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)

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

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

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.

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:

在此处输入图片说明

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM