Back to: ASP.NET Core Web API Tutorials
201 HTTP Status Code in ASP.NET Core Web API
In this article, I will discuss How to Return 201 Created HTTP Status Code from the ASP.NET Core Web API Controller Action Method with Examples. Please read our previous article discussing How to Return 200 OK HTTP Status Code from the ASP.NET Core Web API Controller Action method with Examples.
201 HTTP Status Code
The 201 HTTP Status Code is known as “Created”. It is a success status response code that indicates a request has succeeded and, as a result, a new resource has been created. It is commonly used in response to POST requests that create new entities on the server or some PUT requests that result in the creation of a new resource. The following are some of the key points about the 201 HTTP status code:
- Resource Creation: The 201 HTTP Status Code is specifically used when a new resource has been successfully created as a result of the client’s request. This could be a new record in a database, a new file on a server, or any other type of resource.
- Location Header: When responding with a 201 Status Code, it is a common practice (and often a requirement) to include a Location header in the response. The Location header indicates the URL where the newly created resource can be found.
- Response Body: Although not required, it’s common to include the representation of the newly created resource in the response body. This provides the client with confirmation of what was created and allows the client to see the initial state of the resource without making an additional GET request.
- Typical Usage: This is often used with POST requests but can also be used with PUT requests if the resource was created successfully at the specified URI.
How to Return 201 HTTP Status Code in ASP.NET Core Web API
In ASP.NET Core Web API, we can use the Created, CreatedAtAction, or CreatedAtRoute method to return a 201 Created HTTP Status Code, which indicates that a request has been fulfilled and resulted in the creation of a new resource. The Created, CreatedAtAction, and CreatedAtRoute methods return a 201 Created response with a Location header to the newly created resource. These methods are typically used in POST actions where a new resource has been created as a result of the request. They not only indicate that the resource was successfully created but also provide a URI to access the newly created resource.
We are going to work with the same example that we worked on in our previous article. If you are coming directly to this article, then please create the following Employee model, which we will be using in our controller.
namespace ReturnTypeAndStatusCodes.Models { public class Employee { public int Id { get; set; } public string Name { get; set; } public string Gender { get; set; } public int Age { get; set; } public string Department { get; set; } } }
Using the CreatedAtAction Method in ASP.NET Core Web API
The CreatedAtAction method is used to return a 201 HTTP Status Code and adds a Location header to the response. The header points to the action method that can retrieve the newly created resource. The CreatedAtAction method returns a CreatedAtActionResult that creates a 201 Created HTTP response.
For a better understanding, please modify the Employee Controller as follows. In the below example, the GetEmployee method returns an employee based on the employee ID. The CreateEmployee method creates a new employee and returns the 201 HTTP status code and the response location header with the URL to access the newly created resource.
using ReturnTypeAndStatusCodes.Models; using Microsoft.AspNetCore.Mvc; namespace ReturnTypeAndStatusCodes.Controllers { [Route("api/[controller]")] [ApiController] public class EmployeeController : ControllerBase { //Data Source private static List<Employee> Employees = new List<Employee> { new Employee { Id = 1, Name = "Rakesh", Age = 25, Gender = "Male", Department = "IT" }, new Employee { Id = 2, Name = "Hina", Age = 26, Gender = "Female", Department = "HR" }, new Employee { Id = 3, Name = "Suresh", Age = 27, Gender = "Male", Department = "IT" }, }; [HttpPost] public ActionResult<Employee> CreateEmployee(Employee employee) { // Add and save employee in your database or storage employee.Id = Employees.Count + 1; Employees.Add(employee); // Assuming you have an API for getting the resource // GetEmployee is the name of the action method which takes the employee id and return the employee return CreatedAtAction(nameof(GetEmployee), new { id = employee.Id }, employee); } [HttpGet("{id}")] public ActionResult<Employee> GetEmployee(int id) { var employee = Employees.FirstOrDefault(emp => emp.Id == id); if (employee == null) { // 404 Not Found if the employee does not exist return NotFound(); } // 200 OK with the employee in the response body return Ok(employee); } } }
In this example, after adding the new employee, CreatedAtAction returns a 201 Created status code. The first parameter is the name of the action method (GetEmployee) that can be used to retrieve the new resource. The Second Parameter is an anonymous object that contains route values (in this case, the ID of the new employee), and the third parameter is the newly created response that will come as part of the response body.
Now, run the application, get the port number where your application is running, and then issue a Post request using Postman, as shown in the image below. Here, you can see that we have selected the HTTP method as POST and provided the URL as https://localhost:7128/api/Employee. As it is a POST request, we have selected the body; in the body, we send the RAW data in JSON format and then click on the Send button, as shown in the image below.
Once you click the Send button, it will make an HTTP Post Request to the server by sending the Employee details in the Request body. The server will then process the request, create a new employee, and return the 201 HTTP Status Code along with the employee’s details. To see the same, please select the Response Body tab as shown in the image below:
Along with the 201 Created HTTP Status Code and the response body, the server also set the Location header with the unique URI to access the newly created response. Now, if you select the response header tab, then you will see the following:
Using the CreatedAtRoute Method in ASP.NET Core Web API
The CreatedAtRoute method also returns a 201 HTTP Status Code. It adds a Location header to the response, similar to CreatedAtAction, but using a route name to generate the URL that will be set in the location header. The location header points to the action that can retrieve the newly created resource. So, if you have a named route, you can use the CreatedAtRoute method. This is useful when the route to the action is defined using the Name property in the route’s attribute.
For a better understanding, please modify the Employee Controller as follows. In the example below, the GetEmployee method returns an employee based on the employee ID and is created with a route named GetGetEmployeeRoute (specified using the Name property of the HttpGet attribute). The CreateEmployee method creates a new employee and returns the 201 status code.
using ReturnTypeAndStatusCodes.Models; using Microsoft.AspNetCore.Mvc; namespace ReturnTypeAndStatusCodes.Controllers { [Route("api/[controller]")] [ApiController] public class EmployeeController : ControllerBase { //Data Source private static List<Employee> Employees = new List<Employee> { new Employee { Id = 1, Name = "Rakesh", Age = 25, Gender = "Male", Department = "IT" }, new Employee { Id = 2, Name = "Hina", Age = 26, Gender = "Female", Department = "HR" }, new Employee { Id = 3, Name = "Suresh", Age = 27, Gender = "Male", Department = "IT" }, }; [HttpPost] public ActionResult<Employee> CreateEmployee(Employee employee) { // Add and save employee in your database or storage employee.Id = Employees.Count + 1; Employees.Add(employee); // Assuming you have a named route for getting the resource // GetGetEmployeeRoute is the Route name of the Resource which takes the id and return the employee return CreatedAtRoute("GetGetEmployeeRoute", new { id = employee.Id }, employee); } //Generate Resource with Route Name [HttpGet("{id}", Name = "GetGetEmployeeRoute")] public ActionResult<Employee> GetEmployee(int id) { var employee = Employees.FirstOrDefault(emp => emp.Id == id); if (employee == null) { // 404 Not Found if the employee does not exist return NotFound(); } // 200 OK with the employee in the response body return Ok(employee); } } }
In this example, CreatedAtRoute is used with a named route (“GetGetEmployeeRoute“) to generate the Location header URL. The first parameter is the route’s name, the second is an anonymous object with route values, and the third is the created resource to be returned in the response body.
With the above changes in place, run the application and test the Post action method. It should work as expected in the previous example.
How to Return 201 Status Code without Data:
Both the CreatedAtAction and CreatedAtRoute methods automatically set the HTTP Status Code to 201 Created and include the Location header in the response, which is the URI of the newly created resource. The last parameter in both methods is the newly created resource, which will be included in the response body.
If you don’t want to include the newly created resource data in the response body, then you need to set the last parameter value to null. For a better understanding, please modify the Employee Controller as follows:
using ReturnTypeAndStatusCodes.Models; using Microsoft.AspNetCore.Mvc; namespace ReturnTypeAndStatusCodes.Controllers { [Route("api/[controller]")] [ApiController] public class EmployeeController : ControllerBase { //Data Source private static List<Employee> Employees = new List<Employee> { new Employee { Id = 1, Name = "Rakesh", Age = 25, Gender = "Male", Department = "IT" }, new Employee { Id = 2, Name = "Hina", Age = 26, Gender = "Female", Department = "HR" }, new Employee { Id = 3, Name = "Suresh", Age = 27, Gender = "Male", Department = "IT" }, }; [HttpPost] public ActionResult<Employee> CreateEmployee(Employee employee) { // Add and save employee in your database or storage employee.Id = Employees.Count + 1; Employees.Add(employee); //Without the Newly Created Resource Data //GetGetEmployeeRoute is the Route Name //return CreatedAtRoute("GetGetEmployeeRoute", new { id = employee.Id }, null); //Without the Newly Created Resource Data //GetEmployee is the Action Method Name return CreatedAtAction("GetEmployee", new { id = employee.Id }, null); } //Generate Resource with Route Name [HttpGet("{id}", Name = "GetGetEmployeeRoute")] public ActionResult<Employee> GetEmployee(int id) { var employee = Employees.FirstOrDefault(emp => emp.Id == id); if (employee == null) { // 404 Not Found if the employee does not exist return NotFound(); } // 200 OK with the employee in the response body return Ok(employee); } } }
Using Created Method in ASP.NET Core Web API
The Created method also returns the HTTP Status Code 201. The Created method also adds a Location header to the response, specifying the URI of the newly created resource. There are several overloads of the Created method available, allowing us to specify the URI of the newly created resource and optionally include the value of the created resource in the response body. The following are the three overloaded versions:
Created():
This method will return the 204 Status Code without the URL Location header and will not include the data in the response body. This version of the method is not typically used directly because it does not specify the location of the created resource or include a value in the response body. Instead of 201, it will return the 204 Status Code.
Created(string? uri, [ActionResultObjectValue] object? value):
This overload allows you to return a 201 Created status along with a Location header and a body. The parameters are:
- uri: This is a string representing the URI where the newly created resource can be accessed. This URI is used to populate the Location header in the HTTP response.
- value: This is the object that we want to return in the response body. It represents the newly created resource and is serialized into JSON (or another configured format) in the response.
Created(Uri? uri, [ActionResultObjectValue] object? value):
This overload is similar to the string URI version but takes a Uri object instead of a string. This can be more convenient when you are working with Uri objects directly, ensuring that the URI is valid.
- uri: A Uri object representing the location of the newly created resource. Like the string version, it populates the Location header.
- value: The object to return in the response body, representing the resource.
Example to Understand Created Method in ASP.NET Core Web API
For a better understanding of the above three overloaded methods, please modify the Employee Controller as follows. In the below example, the GetEmployee method is going to return an employee based on the employee ID. The CreateEmployee1 method uses Created(), the CreateEmployee2 method uses Created(Uri uri, object value), and the CreateEmployee3 method uses Created(string uri, object value) overloaded versions. The following example code is self-explained, so please go through the comment lines.
using ReturnTypeAndStatusCodes.Models; using Microsoft.AspNetCore.Mvc; namespace ReturnTypeAndStatusCodes.Controllers { [Route("api/[controller]/[action]")] [ApiController] public class EmployeeController : ControllerBase { // Data Source private static List<Employee> Employees = new List<Employee> { new Employee { Id = 1, Name = "Rakesh", Age = 25, Gender = "Male", Department = "IT" }, new Employee { Id = 2, Name = "Hina", Age = 26, Gender = "Female", Department = "HR" }, new Employee { Id = 3, Name = "Suresh", Age = 27, Gender = "Male", Department = "IT" }, }; // POST: api/Employee/CreateEmployee1 [HttpPost] public ActionResult<Employee> CreateEmployee1(Employee employee) { // Add and save employee in your database or storage employee.Id = Employees.Count + 1; Employees.Add(employee); // Returning 204 Status Code without Location Header and without Response Body return Created(); } // POST: api/Employee/CreateEmployee2 [HttpPost] public ActionResult<Employee> CreateEmployee2(Employee employee) { // Add and save employee in your database or storage employee.Id = Employees.Count + 1; Employees.Add(employee); // Create the URI for the newly created resource as a string // var locationUri = $"https://localhost:7166/api/Employee/GetEmployee/{employee?.Id}"; // Generate the URI for the newly created resource using Url.Action // The Url.Action method generates a fully qualified URL for the specified action. // In this case, it generates the URL for the GetEmployee action, using the id of the newly created employee. var locationUri = Url.Action("GetEmployee", new { id = employee.Id }); // Return 201 Created response with the URI and the employee object return Created(locationUri, employee); } // POST: api/Employee/CreateEmployee3 [HttpPost] public ActionResult<Employee> CreateEmployee3(Employee employee) { // Add and save employee in your database or storage employee.Id = Employees.Count + 1; Employees.Add(employee); // Generate the URI for the newly created resource using Url.Link // The Url.Link method generates an absolute URI based on the specified route name ("GetEmployee") // and route values (new { id = employee.Id }). var locationUri = Url.Link("GetEmployee", new { id = employee.Id }); if (locationUri == null) { // Handle the error or generate a default URI return BadRequest("Unable to generate location URI for the new resource."); } // Return 201 Created response with the URI and the employee object return Created(new Uri(locationUri), employee); } // GET: api/Employee/GetEmployee/1 [HttpGet("{id}", Name = "GetEmployee")] public ActionResult<Employee> GetEmployee(int id) { var employee = Employees.FirstOrDefault(emp => emp.Id == id); if (employee == null) { // 404 Not Found if the employee does not exist return NotFound(); } // 200 OK with the employee in the response body return Ok(employee); } } }
In the above Example:
- CreateEmployee1: This method uses the Created() overload, which returns a 201 status code without specifying a location or including a response body. This is not a common use case and is typically not recommended because it doesn’t provide useful information to the client.
- CreateEmployee2: This method uses the Created(string? uri, [ActionResultObjectValue] object? value) overload. It constructs the location URI as a string and includes both the location and the employee object in the response.
- CreateEmployee3: This method uses the Created(Uri? uri, [ActionResultObjectValue] object? value) overload. It constructs the location URI as a Uri object and includes both the location and the employee object in the response.
With the above changes in place, run the application and test the Post Action Methods, and it should work as expected.
When to use Created, CreatedAtAction and CreatedAtRoute in ASP.NET Core Web API?
In ASP.NET Core Web API, Created, CreatedAtAction, and CreatedAtRoute methods are used to return a 201 Created response, indicating that a resource has been successfully created. Each method has its specific use case based on how you want to generate the URI for the newly created resource. Here’s a detailed explanation of when to use each:
- Created: Use Created when you want to specify the URI of the newly created resource directly as a string or Uri object. This is useful when you have the URI readily available or can construct it manually.
- CreatedAtAction: Use CreatedAtAction when you want to generate the URI for the newly created resource using the name of an action method. This is useful when the resource’s URI is based on another action within the same or a different controller.
- CreatedAtRoute: Use CreatedAtRoute when you want to generate the URI for the newly created resource using a named route. This is useful when the URI is based on a named route defined in your routing configuration.
When Should We Return 201 HTTP Status Code in ASP.NET Core Web API?
In ASP.NET Core Web API, the HTTP status code 201 is returned to indicate that a request has been successfully processed and, as a result, a new resource has been created. Here are specific scenarios when you should return a 201 Status Code:
- POST Requests: This is typically used in response to a POST request where the server has successfully created a new resource.
- PUT Requests: Although less common, a PUT request can also be used to respond to a new resource creation.
In the next article, I will discuss how to Return the 202 HTTP Status Code in ASP.NET Core Web API with Examples. In this article, I explained how to return 201 Created HTTP Status Code in ASP.NET Core Web API with examples. I hope you enjoy this article on “201 HTTP Status Code in the ASP.NET Core Web API.”
var employee = Employees.FirstOrDefault(emp => emp.Id == id);
there is error in above code. could you pleasse look into it.
In the previous code, a route attribute should be added to all three POST action methods for them to function correctly.
[Route(“CreateEmployee1”)]
[Route(“CreateEmployee2”)]
[Route(“CreateEmployee3”)]