route query net multiple asp c# asp.net-web-api asp.net-web-api-routing attributerouting

c# - query - CreadoAtRoute enrutamiento a diferente controlador



web api query string parameters (3)

Cariño, este puede ser un nuevo registro para responder a mi propia pregunta.

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

Hace el truco. es decir, especificando explícitamente el controlador. Trabajé esto al ver que la excepción estaba relacionada con el UrlHelper y leyendo sus documentos ...

Estoy creando un nuevo webapi usando el enrutamiento de atributos para crear una ruta anidada como tal:

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

Sin embargo, quiero devolver una ruta que no está anidada, es decir:

/api/Messages/{id}

que se define en el controlador de mensajes. Sin embargo, la llamada anterior de CreatedAtRoute no resuelve esta ruta y, en su lugar, tira. ¿He hecho algo mal, o no es compatible con el enrutamiento a otro controlador api? nB la ruta que estoy tratando de golpear no es una ruta de atributo, solo una ruta predeterminada.

La excepción es:

Mensaje: "Ha ocurrido un error". ExceptionMessage: "UrlHelper.Link no debe devolver nulo". ExceptionType: "System.InvalidOperationException" StackTrace: "en System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult 1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult 1.ExecuteAsync (CancellationToken cancellationToken) en System.Web.Http.Controllers .ApiControllerActionInvoker.d__0.MoveNext () --- El final del seguimiento de la pila desde la ubicación anterior donde se produjo la excepción --- en System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (Tarea de tarea) en System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification ( Tarea tarea) en System.Runtime.CompilerServices.TaskAwaiter 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.TaskAwaiter 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.TaskAwaiter 1.GetResult () en System.Web.Http.Dispatcher.HttpControllerDispatcher.d__0.MoveNext () "

Si no es compatible con esto, ¿cuál es la forma canónica de devolver un 201 y puedo hacerlo de forma segura?


Simplemente agregando a las respuestas anteriores: en el enrutamiento de atributos:

Me sorprendió el nombre del parámetro, me tomó una hora darme cuenta de que el parámetro debe tener el nombre correcto, de lo contrario, Url Helper devolverá nulo.

es decir, si tiene un método de acción como:

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

Entonces el retorno debería ser:

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

En los ejemplos más simples, la propiedad Id me siguió tirando, así que pensé que ampliaría más en esta respuesta para ayudar a otros a ahorrar tiempo en este pequeño problema.

Vea este ejemplo más complicado para más detalles:

Enrutamiento de atributos y CreatedAtRoute


Tarde a la fiesta pero una respuesta alternativa. Si la acción que está enrutando también usa el enrutamiento de atributos, puede darle un nombre a la ruta y pasarla al método CreatedAtRoute. Esto se hace estableciendo una propiedad de Name en la Route . Siguiendo su ejemplo de publicación, considere la siguiente acción.

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

Tenga en cuenta que la propiedad Name en el atributo de ruta, [Route("api/messages/{id}", Name="GetMessage")] , se establece en "GetMessage" . Al hacer esto, podemos llamar al método CreatedAtRoute desde la acción PostChannelMessage y pasar el nombre de la ruta como PostChannelMessage :

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

Este es un escenario que encontré y mi búsqueda llevó aquí, así que pensé que publicaría esta respuesta alternativa en caso de que ayudara a alguien más.