CreatedAtRoute路由到不同的控制器

Dan*_*anH 36 c# asp.net-web-api attributerouting asp.net-web-api-routing

我正在使用属性路由创建一个新的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);
    }
Run Code Online (Sandbox Code Playgroud)

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

/api/Messages/{id}
Run Code Online (Sandbox Code Playgroud)

这是在消息控制器上定义的.但是,上面的CreatedAtRoute调用不解析此路线而是抛出.我做错了什么,或者它不支持路由到不同的api控制器?我试图点击的路线不是属性路线,只是默认路线.

例外是:

消息:"发生了错误." ExceptionMessage:"UrlHelper.Link不能返回null." ExceptionType:"System.InvalidOperationException"StackTrace:"at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult 1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult1.ExecuteAsync(CancellationToken cancellationToken)at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()---堆栈跟踪结束从抛出异常的上一个位置---在System.Runtime.Compiler服务的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务),System.Runtime.CompilerServices.TaskAwaiter的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)1.GetResult() at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>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的规范方法是什么?我可以以重构安全的方式进行吗?

Dan*_*anH 51

哦,亲爱的,这可能是回答我自己的问题的新纪录.

return CreatedAtRoute("DefaultApi", new { controller = "messages", id = message.Id }, message);
Run Code Online (Sandbox Code Playgroud)

诀窍.即明确指定控制器.我通过看到异常与UrlHelper相关并阅读其文档来解决这个问题...


cee*_*eej 37

晚到党,但另一个答案.如果要路由到的操作也使用属性路由,则可以为路由指定名称并将其传递给CreatedAtRoute方法.这是通过在上面设置Name属性来完成的Route.根据您的帖子示例,请考虑以下操作.

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

请注意,Nameroute属性的属性[Route("api/messages/{id}", Name="GetMessage")]设置为"GetMessage".通过这样做,我们可以CreatedAtRoutePostChannelMessage动作调用方法并传递路由名称,如下所示:

return CreatedAtRoute("GetMessage", new { id = message.Id }, message);
Run Code Online (Sandbox Code Playgroud)

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