Подтвердить что ты не робот

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, и могу ли я сделать это безопасным способом?

4b9b3361

Ответ 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