WebApi2 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);
}
Однако я хочу вернуть маршрут, который не вложен i.e.:
/api/Messages/{id}
который определен в контроллере сообщений. Однако вызов, описанный в CreateAtRoute выше, не разрешает этот маршрут и вместо этого бросает. Я сделал что-то неправильно или не поддерживает маршрутизацию на другой контроллер api? нотабене маршрут, который я пытаюсь ударить, не является маршрутом атрибута, просто по умолчанию.
Исключение составляет:
Сообщение: "Произошла ошибка". ExceptionMessage: "UrlHelper.Link не должен возвращать null". ExceptionType: "System.InvalidOperationException" StackTrace: "в System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult 1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult
1.ExecuteAsync(CancellationToken cancelationToken) в System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext() --- Конец трассировки стека из предыдущего места, где исключение было отправлено --- в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(задача задачи) в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(задача задачи) в 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() в System.Web.Http.Dispatcher.HttpControllerDispatcher.d__0.MoveNext()"
Если это не поддерживает это, каков канонический способ вернуть 201, и могу ли я сделать это безопасным способом?
Ответы
Ответ 1
О, дорогая, это может быть новая запись для ответа на мой собственный вопрос.
return CreatedAtRoute("DefaultApi", new { controller = "messages", id = message.Id }, message);
делает трюк. то есть явно указывая контроллер. Я работал над этим, увидев, что исключение связано с UrlHelper и читает его документы...
Ответ 2
Поздно к партии, но альтернативный ответ. Если действие, к которому выполняется маршрутизация, также использует маршрутизацию атрибутов, вы можете указать маршрут имени и передать его методу CreatedAtRoute. Это делается путем установки свойства Name
на Route
. Следуя вашему примеру, рассмотрите следующее действие.
// 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);
Это сценарий, с которым я столкнулся, и мои поиски привели сюда, поэтому я подумал, что отправлю этот альтернативный ответ, если он поможет кому-то еще.
Ответ 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 продолжало отбрасывать меня, поэтому я подумал, что в этом ответе я расскажу больше об этом, чтобы помочь сохранить время в этой маленькой проблеме.
Подробнее см. более сложный пример:
Маршрутизация атрибутов и CreatedAtRoute