'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);
}
Solution 1:[1]
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);
}
Solution 2:[2]
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 };
}
Solution 3:[3]
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);
Solution 4:[4]
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);
}
Solution 5:[5]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Gildor |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | David Oganov |
| Solution 5 | Community |


