简体   繁体   中英

How can I code a Created-201 response using IHttpActionResult

How can I code a Created-201 response using IHttpActionResult ?

IHttpActionResult has only these options

  • Ok
  • List item
  • NotFound
  • Exception
  • Unauthorized
  • BadRequest
  • Conflict Redirect
  • InvalidModelState

What I am doing now is this code below, but I would like to use IHttpActionResult and not HttpResponseMessage

public IHttpActionResult Post(TaskBase model)
{
    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, model);
    response.Headers.Add("Id", model.Id.ToString());
    return ResponseMessage(response);
}

If your view derives from ApiController , you should be able to call the Created method from base class to create such a response.

Sample:

[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);
}
return Content(HttpStatusCode.Created, "Message");

Content is returning NegotiatedContentResult. NegotiatedContentResult is implements IHttpActionResult.

在此处输入图片说明

在此处输入图片说明

A similar problem: If you want to send NotFound with the message.

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

Or:

return Content(HttpStatusCode.Created, Class object);
return Content(HttpStatusCode.NotFound, Class object);

In ASP.NET Core, an IActionResult can be returned. This means you can return a ObjectResult with a 201 status code.

[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 };
}

Alternatively, to what Chris is suggesting, what you can do is return an IActionResult, using or " StatusCode " method, the following way:

[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);
}

I know this is an old thread but you might want to take a look at my solution here . Its a little more than needed but sure will do the job.

Steps:

Define a custom attribute:

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

Decorate the uniquely identifying property of your model with a custom 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; }
    }

Add a new Created(T yourobject); method to a BaseController which inherits from ApiController. Inherit all your controllers from this 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);
     }

Its pretty simple without having to worry about writing so much in every method. All you got to do is just call Created(yourobject);

The Created() method would still work if you forget to decorate or cannot decorate your model(for some reason). The location header would miss the Id though.

Your unit test for that controller should take care of this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM