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.Результаты.CreatedAtRouteNegotiatedContentResult1.Execute() at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult1.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.TaskAwaiter1.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 продолжало выбрасывать меня, поэтому я думал, что расширю его больше в этот ответ поможет сэкономить время других на этой маленькой проблеме.

см. Этот более сложный пример для более подробной информации:

маршрутизация атрибутов и CreatedAtRoute