ASP.NET CORE,Web API:没有路由匹配提供的值

时间:2016-09-12 21:52:49

标签: c# asp.net-mvc-routing .net-core asp.net-core-webapi api-versioning

我在asp.net core(web api)中的路由有一些问题。

我有这个控制器(简化):

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

    var val = CreatedAtRoute("GetDocument", new { version = "1", controller = "Document", guid = doc.Guid.ToString("N")}, document);

    return val;
}
}

如果我调用Create,则会创建文档并创建路由对象,但是我收到错误"没有路由匹配提供的值"并获得500状态。

我可以直接调用GetByGuid,没有任何问题。

我无法找到asp.net核心的任何调试帮助(就像任何现有的路由调试器一样)。

我将不胜感激任何帮助!

修改 看起来这将是微软的版本控制包中的一个错误..如果我定义修复路由/ api / v1 / [控制器]它正在工作。

但那对我来说不是解决方案。

12 个答案:

答案 0 :(得分:6)

我会回答我自己的问题: 这真是微软版本化软件包中的一个错误,它很快就会修复。

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

答案 1 :(得分:3)

ASP.net核心3

为什么会出现此问题:

“作为寻址dotnet/aspnetcore#4849的一部分, ASP.NET Core MVC trims the suffix Async from action names by default 。从ASP.NET Core 3.0开始,此更改会影响路由和链接的生成。”

查看更多信息: https://docs.microsoft.com/en-us/dotnet/core/compatibility/aspnetcore#mvc-async-suffix-trimmed-from-controller-action-names

@Chris Martinez在this thread中说:

更改的原因并非任意;它解决了另一个错误。如果您不受上述错误的影响,并希望像往常一样继续使用Async后缀。

如何解决

重新启用它:

services.AddMvc(options =>
{
   options.SuppressAsyncSuffixInActionNames = false;
});

您现在应该像这样传递包含后缀createActionName的{​​{1}}参数:

Async

答案 2 :(得分:2)

我只是使用了返回CreatedAtAction("ActionMethodName", dto);,直到他们修复了该错误。

答案 3 :(得分:2)

我知道这篇文章来自2017年,但我仍然面临着同样的问题,并最终落到了这里。而且看起来您从未发现自己的错误,我将在这里为发现该帖子的其他人写出来。

问题在于,当您致电:

CreatedAtRoute("GetDocument", new { version = "1", controller = "Document", guid = doc.Guid.ToString("N")}, document);

您要告诉程序寻找“ GetDocument”函数,该函数接收3个参数,在这种情况下为3个字符串,但是实际的“ GetDocument”定义仅接收1个字符串作为“ 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};
}

因此,要使它正常工作,您应该像这样:

CreatedAtRoute("GetDocument", new { guid = doc.Guid.ToString("N")}, document);

另一种选择是使用3个字符串创建一个新的get方法,也许您必须将其称为不同于“ GetDocument”的东西。

希望这有助于下一个寻找此:D的人。

答案 4 :(得分:2)

我有相同的症状,但原因是其他原因。基本上,我的操作方法以Async结尾的事实并不令人满意。当我将操作方法​​从GetAsync重命名为Get或将[ActionName("GetAsync")]添加到操作中时,它就起作用了。

来源:https://github.com/microsoft/aspnet-api-versioning/issues/601

答案 5 :(得分:1)

当您使用CreatedAtAction返回201时,发生此错误的另一个原因是b / c,ASP.NET会向响应中添加一个Location标头,并在URL中添加资源可以访问。它使用actionName来执行此操作,因此方法名称需要与控制器上的有效方法匹配。例如:

return CreatedAtAction("GetUser", new { id = user.UserId }, user);

如果GetUser不存在,则呼叫将失败。可能使用更好的做法:

return CreatedAtAction(nameof(GetUser), new { id = user.UserId }, user);

dev guide apidocs

答案 6 :(得分:1)

这对我有用... https://www.josephguadagno.net/2020/07/01/no-route-matches-the-supplied-values

我的 get-async 是...

[HttpGet("{id}", Name = nameof(GetSCxItemAsync))]                            
public async Task<ActionResult<SCxItem>> GetSCxItemAsync(Guid id)

但是为了解决路由错误,我必须在函数声明之前添加以下内容...

[ActionName(nameof(GetSCxItemAsync))]

答案 7 :(得分:0)

代替此:

<span> 
   <a [href]="getFileLink(document.docID)" target="_blank">
      {{document.comments}}
   </a>
</span>

将您的退货更改为以下内容:

CreatedAtRoute("GetDocument", new { version = "1", controller = "Document", guid = doc.Guid.ToString("N")}, document);

答案 8 :(得分:0)

大多数其他答案提到的答案,我已经尝试过了,但是没有用。但是我知道,如果我们在您的启动课程中将endpoints.MapControllers();更改为endpoints.MapDefaultControllerRoute();,该错误将消失:

app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute(); // MapControllers();
            });

,如果您想查看这两个端点的不同之处,可以visit this

答案 9 :(得分:0)

以防万一,如果您像我一样,不喜欢从任何内置的ControllerX基类继承,那么如果使用以下语句,您可能会遇到此问题

  new CreatedAtActionResult(nameof(GetBookOf),
            nameof(BooksController),
            new {id = book.Id.ToString("N")},
            book)

这是因为上述语句中的第二个参数希望我们传递不带后缀Controller的构造函数名称。

因此,如果您按照以下方式进行更改,那么它将正常工作。

  new CreatedAtActionResult(nameof(GetBookOf),
            "Books",
            new {id = book.Id.ToString("N")},
            book)

答案 10 :(得分:0)

我要为其他一些不幸的灵魂坚持这一点,因为我花了太长时间弄清楚我做错了什么。

这是错误的:

app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());

这样做是通过返回默认路由 [controller] 来掩盖问题,而您希望它返回的是 [controller]\{newly generated id}

这是正确的:

return CreatedAtAction(nameof(GetUser), new { id = user.UserId }, user);

然而,有一种边缘情况会失败,即 user.UserIdnull。我认为这失败是因为需要 id 参数,所以不能是 null,因此路由没有绑定。它失败是件好事,因为如果没有,那么您将创建一个垃圾路由,但错误消息可能比它可能更神秘。

在我的例子中,我返回的是输入对象上的 Id,它是空的,而不是输出对象上新生成的 Id。

答案 11 :(得分:0)

就我而言,这是复制/粘贴错误。 CreatedAtAction 方法具有错误的操作名称参数。确保第一个参数(actionName 参数)与操作名称(函数名称)匹配。更正后的代码如下所示:

enter image description here