CreatedAtRoute маршрутизации на другой контроллер
Я создаю новый 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.Ссылка не должна возвращать null." ExceptionType: "Система.Исключение InvalidOperationException" StackTrace: "at System.Сеть.Http.Результаты.CreatedAtRouteNegotiatedContentResult
1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult
1.ExecuteAsync(cancellationToken CancellationToken) в системе.Сеть.Http.Контроллеры.ApiControllerActionInvoker.Д__0.MoveNext () - - - конец трассировки стека из предыдущего местоположения, где исключение был брошен - - - на систему.Во время выполнения.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача задачи) в системе.Во время выполнения.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) в системе.Во время выполнения.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 () в системе.Сеть.Http.Диспетчер.HttpControllerDispatcher.Д__0.MoveNext ()"
если он не поддерживает это, каков канонический способ вернуть 201 и могу ли я сделать это безопасным способом рефакторинга?
3 ответов
О боже, это может быть новый рекорд за ответ на мой собственный вопрос.
return CreatedAtRoute("DefaultApi", new { controller = "messages", id = message.Id }, message);
делает трюк. т. е. явное указание контроллера. Я работал над этим, видя, что исключение связано с UrlHelper и читая его документы...
опоздал на вечеринку, но альтернативный ответ. Если действие, к которому выполняется маршрутизация, также использует маршрутизацию атрибутов, можно присвоить маршруту имя и передать его методу CreatedAtRoute. Это делается путем установки Name
собственности на Route
. Следуя примеру post, рассмотрите следующее действие.
// GET: api/Messages/5
[Route("api/messages/{id}", Name="GetMessage")]
public async Task<IHttpActionResult> GetMessage(int id)
{
// get the message
}
отметим, что Name
свойство атрибута маршрута,[Route("api/messages/{id}", Name="GetMessage")]
, установлено "GetMessage"
. Делая это, мы можем вызвать CreatedAtRoute
метод PostChannelMessage
действие и пройдите в названии маршрута так:
return CreatedAtRoute("GetMessage", new { id = message.Id }, message);
это сценарий, с которым я столкнулся, и мой поиск привел сюда, поэтому я подумал, что опубликую этот альтернативный ответ, если он поможет кому-то еще.
просто добавив к ответам выше:о маршрутизации атрибутов:
Я был пойман именем параметра, мне потребовался час, чтобы понять, что параметр должен быть правильно назван, иначе помощник Url вернет null.
i.e если у вас есть метод действия, например:
[Route("api/messages/{id}", Name="GetAction")]
public IHttpActionResult GetEntity(int mySpecialUniqueId)
{
// do some work.
}
тогда возврат должен быть:
return CreatedAtRoute("GetAction", new { mySpecialUniqueId = entity.Id }, entity);
на более простых примерах свойство Id продолжало выбрасывать меня, поэтому я думал, что расширю его больше в этот ответ поможет сэкономить время других на этой маленькой проблеме.
см. Этот более сложный пример для более подробной информации: