Routage CreatedAtRoute vers différents contrôleurs
je crée un nouveau webapi en utilisant l'attribut routing pour créer une route imbriquée comme suit:
// 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);
}
je veux cependant retourner un itinéraire qui n'est pas imbriqué i.e.:
/api/Messages/{id}
qui est défini sur le contrôleur des messages. Cependant L'appel CreatedAtRoute ci-dessus ne résout pas cette route et lance plutôt. Ai-je fait quelque chose de mal, ou ne supporte-t-il pas le routage vers un autre contrôleur d'api? N. B. la route que j'essaie de suivre est pas une route d'attribut, juste une route par défaut.
l'exception est:
Message: "Une erreur s'est produite." ExceptionMessage: "UrlHelper.Le lien ne doit pas retourner null." ExceptionType: "Le Système De.InvalidOperationException" StackTrace: "au Système.Web.Http.Résultat.Createdatedatroutenegotiatedcontentresult
1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult
1.ExecuteAsync (Annulationtoken cancellationToken)au système.Web.Http.Contrôleur.ApiControllerActionInvoker.d _ _ 0.MoveNext() --- Fin de la trace de la pile à partir de l'emplacement précédent où l'exception a été levée --- à Système de.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (tâche tâche) au système.Runtime.CompilerServices.TaskAwaiter.Handlenonsuccèsanddebuggernotification (tâche) au système.Runtime.CompilerServices.TaskAwaiter1.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() au Système.Web.Http.Répartiteur.HttpControllerDispatcher.d _ _ 0.MoveNext () "
S'il ne supporte pas cela, quelle est la façon canonique de retourner un 201 et puis-je le faire de façon sécuritaire?
3 réponses
Oh mon Dieu, c'est peut-être un nouveau record pour répondre à ma propre question.
return CreatedAtRoute("DefaultApi", new { controller = "messages", id = message.Id }, message);
fait l'affaire. c'est à dire de spécifier explicitement le contrôleur. J'ai travaillé cela en voyant que l'exception était liée au Helper URL et à la lecture de ses docs...
la Fin de la partie, mais une alternative de réponse. Si l'action que vous routez utilise également un routage d'attribut, vous pouvez donner un nom à la route et passer ce nom à la méthode CreatedAtRoute. Ceci est fait en définissant une propriété Name
sur la propriété Route
. En suivant votre exemple de post, considérez l'action suivante.
// GET: api/Messages/5
[Route("api/messages/{id}", Name="GetMessage")]
public async Task<IHttpActionResult> GetMessage(int id)
{
// get the message
}
notez que la propriété Name
de l'attribut route, [Route("api/messages/{id}", Name="GetMessage")]
, est définie à "GetMessage"
. En faisant cela nous pouvons appeler la méthode CreatedAtRoute
de l'action PostChannelMessage
et passer dans le nom de route comme ainsi:
return CreatedAtRoute("GetMessage", new { id = message.Id }, message);
c'est un scénario que j'ai rencontré et mes recherches ont mené ici donc pensé que je voudrais poster cette réponse alternative au cas où il aide quelqu'un d'autre.
ajoute simplement aux réponses ci-dessus: sur le routage des attributs:
j'ai été surpris par le nom du paramètre, j'ai mis une heure à réaliser que le paramètre doit être nommé correctement sinon L'Helper Url retournera null.
I. e si vous avez une méthode d'action comme:
[Route("api/messages/{id}", Name="GetAction")]
public IHttpActionResult GetEntity(int mySpecialUniqueId)
{
// do some work.
}
alors le retour doit être:
return CreatedAtRoute("GetAction", new { mySpecialUniqueId = entity.Id }, entity);
sur les exemples plus simples, la propriété Id Je n'arrêtais pas de me jeter donc j'ai pensé que je voudrais développer plus dans cette réponse pour aider à sauver d'autres temps sur cette petite question.
Voir cet exemple plus compliqué pour plus de détails: