Как я могу закодировать ответ Created-201 с помощью IHttpActionResult?

IHttpActionResult имеет только эти параметры

  • ОК
  • Пункт списка
  • Не обнаружена
  • Исключение
  • неразрешенный
  • BadRequest
  • Перенаправление конфликта
  • InvalidModelState

Сейчас я делаю этот код ниже, но я бы хотел использовать IHttpActionResult, а не HttpResponseMessage

public IHttpActionResult Post(TaskBase model)
{
    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, model);
    response.Headers.Add("Id", model.Id.ToString());
    return ResponseMessage(response);
}
23
Devsined 27 Май 2014 в 18:39
1
Здесь есть реализация strathweb.com/2013/06/… но мне это очень не нравится. Я предпочитаю работать с HttpResponseMessage, в котором я могу указать все глаголы и тело только что вызванного метода Request.CreateRespose().
 – 
Felipe Oriani
27 Май 2014 в 18:55

5 ответов

Лучший ответ

Если ваше представление является производным от ApiController, вы должны иметь возможность вызвать метод Created из базового класса для создания такого ответа.

Образец:

[Route("")]
public async Task<IHttpActionResult> PostView(Guid taskId, [FromBody]View view)
{
    // ... Code here to save the view

    return Created(new Uri(Url.Link(ViewRouteName, new { taskId = taskId, id = view.Id })), view);
}
20
Gildor 27 Май 2014 в 18:59
Как я могу добавить URI с помощью моего текущего контроллера API?
 – 
Devsined
27 Май 2014 в 21:31
Ваш контроллер наследует от ApiController?
 – 
Gildor
28 Май 2014 в 07:05
Да, это так. У меня есть возможность возврата Created. Но мне трудно вернуть Uri контроллера плюс идентификатор. Я возвращаюсь сейчас просто любым Ури.
 – 
Devsined
29 Май 2014 в 00:11
2
Или, что еще лучше, CreatedAtRoute msdn.microsoft.com/en-us/library/…
 – 
George Helyar
14 Сен 2016 в 14:55

В ASP.NET Core можно вернуть IActionResult. Это означает, что вы можете вернуть ObjectResult с кодом состояния 201.

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody] CreateModel createModel)
{
    // Create domain entity and persist
    var entity = await _service.Create(createModel);

    // Return 201
    return new ObjectResult(entity) { StatusCode = StatusCodes.Status201Created };
}
13
chris31389 29 Мар 2021 в 11:17
С 2016 года сталкивались ли вы с чванством и почему это не идеально для этого?
 – 
Rafael Herscovici
12 Ноя 2020 в 22:05
Я думаю, что с чванством вы можете добавить атрибуты над методом, которые сообщают чванству, какие статусы возврата возможны и какой будет форма объекта.
 – 
chris31389
18 Ноя 2020 в 00:52
Возможно, «должен» здесь не подходящее слово. Это могло бы". Вы можете возвращать фактические модели или генерировать исключения, что во многих случаях более элегантно.
 – 
Jonas Stensved
17 Мар 2021 в 18:52
return Content(HttpStatusCode.Created, "Message");

Контент возвращает NegotiatedContentResult. NegotiatedContentResult реализует IHttpActionResult.

enter image description here

enter image description here

Аналогичная проблема: если вы хотите отправить NotFound с сообщением.

return Content(HttpStatusCode.NotFound, "Message");

Или же:

return Content(HttpStatusCode.Created, Class object);
return Content(HttpStatusCode.NotFound, Class object);
10
miragessee 21 Дек 2017 в 06:24

В качестве альтернативы тому, что предлагает Крис, вы можете вернуть IActionResult, используя метод или "StatusCode", следующим образом:

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody] CreateModel createModel)
{
    // Create domain entity and persist
    var entity = await _service.Create(createModel);

    // Return 201
    return StatusCode(StatusCodes.Status201Created, entity);
}
0
David Oganov 8 Апр 2022 в 14:22

Я знаю, что это старый поток, но вы можете взглянуть на мое решение здесь. Его немного больше, чем нужно, но он наверняка выполнит свою работу.

Шаги:

Определите настраиваемый атрибут:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class UniqueIdAttribute: Attribute
    {
    }

Украсьте однозначно идентифицирующее свойство вашей модели настраиваемым атрибутом:

   public class Model
    {
        public List<Model> ChildModels { get; set; }
        [UniqueId]
        public Guid ModelId { set; get; }
        public Guid ? ParentId { set; get; }
        public List<SomeOtherObject> OtherObjects { set; get; }
    }

Добавьте новый метод Created(T yourobject); в BaseController, который наследуется от ApiController. Наследуйте все свои контроллеры от этого BaseController:

CreatedNegotiatedContentResult<T> Created<T>(T content)
    {
        var props =typeof(T).GetProperties()
        .Where(prop => Attribute.IsDefined(prop, typeof(UniqueIdAttribute)));
        if (props.Count() == 0)
        {
            //log this, the UniqueId attribute is not defined for this model
            return base.Created(Request.RequestUri.ToString(), content);
        }
        var id = props.FirstOrDefault().GetValue(content).ToString();
        return base.Created(new Uri(Request.RequestUri + id), content);
     }

Это довольно просто, не беспокоясь о написании так много в каждом методе. Все, что вам нужно сделать, это просто позвонить Created(yourobject);

Метод Created () все равно будет работать, если вы забудете украсить или не можете украсить свою модель (по какой-то причине). Однако в заголовке местоположения не будет идентификатора.

Ваш модульный тест для этого контроллера должен позаботиться об этом.

-2
Community 23 Май 2017 в 14:46