【问题标题】:CreatedAtRoute routing to different controllerCreatedAtRoute 路由到不同的控制器
【发布时间】:2014-06-18 12:19:19
【问题描述】:

我正在创建一个新的 webapi,使用属性路由来创建嵌套路由:

    // PUT: api/Channels/5/Messages
    [ResponseType(typeof(void))]
    [Route("api/channels/{id}/messages")]
    public async Task<IHttpActionResult> PostChannelMessage(int id, Message message)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != message.ChannelId)
        {
            return BadRequest();
        }

        db.Messages.Add(message);
        await db.SaveChangesAsync();

        return CreatedAtRoute("DefaultApi", new { id = message.Id }, message);
    }

但是,我想返回一个未嵌套的路由,即:

/api/Messages/{id}

在消息控制器上定义。然而,上面的 CreatedAtRoute 调用并没有解决这个路由而是抛出。我做错了什么,还是不支持路由到不同的 api 控制器?注意我要命中的路由不是属性路由,只是默认路由。

例外是:

消息:“发生错误。” ExceptionMessage:“UrlHelper.Link 不得返回 null。” 异常类型:“System.InvalidOperationException” StackTrace:“在 System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult1.ExecuteAsync(CancellationToken cancelToken) at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext() --- 堆栈跟踪从上一个位置结束异常被抛出---在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在 System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Controllers.ActionFilterResult.&lt;ExecuteAsync&gt;d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()在 System.Web.Http.Dispatcher.HttpControllerDispatcher.d__0.MoveNext()"

如果它不支持这一点,返回 201 的规范方法是什么?我可以以重构安全的方式来做吗?

【问题讨论】:

    标签: c# asp.net-web-api asp.net-web-api-routing attributerouting


    【解决方案1】:

    天哪,这可能是回答我自己问题的新记录。

    return CreatedAtRoute("DefaultApi", new { controller = "messages", id = message.Id }, message);
    

    成功了。即明确指定控制器。我通过看到异常与 UrlHelper 相关并阅读它的文档来解决这个问题......

    【讨论】:

    • CreatedAtAction 也会这样做
    【解决方案2】:

    聚会迟到了,但另一种答案。如果要路由到的操作也使用属性路由,则可以为路由命名并将其传递给 CreatedAtRoute 方法。这是通过在Route 上设置Name 属性来完成的。按照您的帖子示例,考虑以下操作。

    // GET: api/Messages/5
    [Route("api/messages/{id}", Name="GetMessage")]
    public async Task<IHttpActionResult> GetMessage(int id)
    {
        // get the message
    }
    

    请注意,路由属性[Route("api/messages/{id}", Name="GetMessage")] 上的Name 属性设置为"GetMessage"。通过这样做,我们可以从 PostChannelMessage 操作中调用 CreatedAtRoute 方法,并像这样传递路由名称:

    return CreatedAtRoute("GetMessage", new { id = message.Id }, message);
    

    这是我遇到的一个场景,我的搜索在这里引导,所以我想我会发布这个替代答案,以防它帮助其他人。

    【讨论】:

    • 谢谢,这是我使用 Web API 2 + 属性路由的缺失链接。
    • 谢谢@Jess,我一直在寻找解决方案,效果很好!
    • 这是第一个也是主要的答案,解释了为什么 MS 的意思是“routeName”100+ 赞成票。谢谢!
    【解决方案3】:

    只是在上面的答案中添加:关于属性路由:

    我被参数名称所吸引,花了我一个小时才意识到参数需要正确命名,否则 Url Helper 将返回 null。

    即,如果您有类似的操作方法:

    [Route("api/messages/{id}", Name="GetAction")]
    public IHttpActionResult GetEntity(int mySpecialUniqueId)
    {
        // do some work.
    }
    

    那么返回应该是:

    return CreatedAtRoute("GetAction", new { mySpecialUniqueId = entity.Id }, entity);
    

    在更简单的例子中,Id 属性一直让我失望,所以我想我会在这个答案中更多地扩展它,以帮助在这个小问题上节省其他人的时间。

    查看这个更复杂的例子了解更多细节:

    Attribute Routing and CreatedAtRoute

    【讨论】:

      【解决方案4】:

      对于 dotnet 5,解决方案略有不同:

      带有 GET 方法的控制器应该如下所示:

      [Route("api/[controller]")]
      [ApiController]
      public class ItemController : ControllerBase
      {
          [HttpGet("{id}", Name = nameof(Get))]
          public ActionResult Get([FromRoute] int id)
          {
              // code here.
          }
      }
      

      还有像这样的CreatedAtAction 方法:

      return CreatedAtAction(nameof(ItemController.Get), "Item", new { item.Id }, item);
      
      

      可以直接指定到控制器的路由作为CreatedAtAction方法的第二个参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-09
        • 1970-01-01
        • 2016-10-31
        • 1970-01-01
        • 2013-11-04
        • 2013-09-24
        • 2016-03-29
        • 1970-01-01
        相关资源
        最近更新 更多