【问题标题】:ASP.NET Core "CreatedAtRoute" FailureASP.NET Core“CreatedAtRoute”失败
【发布时间】:2016-08-02 07:07:07
【问题描述】:

在我的 ASP.NET Core 应用程序中,我有一个这样的控制器操作:

[HttpPost]
public async Task<IActionResult> CreateSubscriber([FromBody] SubscriberDef subscriber)
{
    //...implementation removed

    var link = Url.Link("SubscriberLink", new { id = subscriber.ID });
        return Created(link, null);
}

上面的代码按预期工作。但是,如果我使用内置方法“CreatedAtRoute”,则会出现异常:

[HttpPost]
public async Task<IActionResult> CreateSubscriber([FromBody] SubscriberDef subscriber)
{
    //...implementation removed

    return CreatedAtRoute("SubscriberLink", new { id = subscriber.ID });
}

例外是:

System.InvalidOperationException:没有路由与提供的值匹配。

异常导致服务返回 500 状态码。

在任何一种情况下都是相同的路线,所以我不知道为什么第一个示例可以正常工作,而第二个则不能。

我的project.json 包含以下内容:

"frameworks": {
  "dnx46": { },
  "dnxcore50": { }
},

为了参考,命名路线由两部分组成。首先是控制器前缀:

[Route("api/[controller]")]
public class SubscribersController : Controller
{
    // ...
}

其次是 GET 操作,其中实际的 "SubscriberLink" 路由命名:

[HttpGet("{id}", Name = "SubscriberLink")]
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(Subscriber))]
public async Task<IActionResult> GetSubscriber(Guid id)
{
    //...implementation removed...
    return Ok(subscriber);
}

想法?

【问题讨论】:

  • SubscriberLink 路由名称在哪里定义?
  • @haim770 在最后的代码 sn-p 中定义。
  • var link = Url.Link("SubscriberLink", new { id = subscriber.ID }); 是返回正确的 Url 还是不抛出异常?
  • 这是一个很好的例子,说明了一个经过充分研究和很好解释的问题。干杯!

标签: c# asp.net-core


【解决方案1】:

简答

您使用了错误的 CreatedAtRoute 重载。请改用接受三个参数的重载。

工作示例

例如,以下在我的机器上工作。

[Route("api/[controller]")]
public class SubscribersController : Controller
{
    public IActionResult Index()
    {
        var subscriber = new
        {
            Id = Guid.NewGuid(),
            FirstName = "Shaun",
            LastName = "Luttin"
        };

        // overload with three arguments
        return CreatedAtRoute(
            routeName: "SubscriberLink",
            routeValues: new { id = subscriber.Id },
            value: subscriber);
    }

    [HttpGet("{id}", Name = "SubscriberLink")]
    public IActionResult GetSubscriber(Guid id)
    {
        var subscriber = new
        {
            Id = id,
            FirstName = "Shaun",
            LastName = "Luttin"
        };

        return new JsonResult(subscriber);
    }
}

详情

结果是 201 响应。响应的正文包含我们创建的实体的详细信息(value 参数),响应的 Location 标头包含实体的 URI。

CreatedAtRoute 有三个重载。

CreatedAtRoute(object routeValues, object value)
CreatedAtRoute(string routeName, object value)
CreatedAtRoute(string routeName, object routeValues, object value)

如果我们想传递一个路由名称和路由值,我们使用带有三个参数的重载。如果我们不想返回我们创建的实体的详细信息,我们可以将null 作为第三个参数,

【讨论】:

  • 应该是 [Route("api/[controller]", Name = "SubscriberLink")] 因为在您的情况下,您设置的是路由模板,而不是名称。
  • 这是不正确的。新的HttpGetAttribute 确实定义了一个Name 属性,还实现了提供路由名称的IRouteTemplateProvider
  • @haim770 已修复。 :) 感谢您的反馈。
  • OP 使用 CreatedAtRoute(string routeName, object value),这似乎是正确的重载。
  • 噢!我认为第一个和第二个重载具有误导性和误解。每当提供Location 标头时,确实 有必要提供 相关路由和routeValues。相反,从不需要为回复提供内容。再说一遍,恕我直言,这些过载都被抬高了。简而言之,此时只有第三个重载有任何价值。感谢您的提醒!
猜你喜欢
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 2021-08-25
  • 2016-10-16
  • 2018-04-28
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多