200 HTTP Status Code in ASP.NET Core Web API

200 HTTP Status Code in ASP.NET Core Web API

In this article, I will discuss How to Return 200 HTTP Status Code from the ASP.NET Core Web API Controller Action method with Examples. Please read our previous article, where we overview the HTTP status code. We will work with the same example we created in our Controller Action Return Types in the ASP.NET Core Web API article.

How Do We Return Proper HTTP Status Codes in ASP.NET Core Web API?

Returning proper HTTP status codes in an ASP.NET Core Web API is important for conveying the outcome of HTTP requests to clients. HTTP status codes provide a standardized way to indicate the success or failure of a request, along with additional context about the response.

Understand HTTP Status Codes
  • 2xx Success: Indicates that the client’s request was received, understood, and accepted (e.g., 200 OK, 201 Created, 202 Accepted, 204 No Content) by the server.
  • 3xx Redirection: Indicates that further action needs to be taken by the client to complete the request, e.g., 301 Moved Permanent, 302 Moved Temporarily, or sometimes it is called Found.
  • 4xx Client Error: Indicates an error that seems to have been caused by the client (e.g., 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed).
  • 5xx Server Error: Indicates that the server failed to fulfill a valid request (e.g., 500 Internal Server Error, 503 Service Unavailable, 504 Gateway Timeout).

To return the proper HTTP Status Codes, the ASP.NET Core Framework provides some built-in methods, and using these methods, we can format our HTTP response. And the best thing is that we don’t need to remember all these methods. We need to right-click on the ControllerBase class and choose to go to definition, and here, you will see many methods to return different types of status codes.

200 HTTP Status Code:

In ASP.NET Core Web API, the HTTP status code 200 OK indicates that a request has been successfully processed. This status code is commonly used in RESTful APIs for GET, PUT, POST, and DELETE operations when they are completed successfully and, in some cases, return data.

How to Return 200 HTTP Status Code in ASP.NET Core Web API?

To return a 200 HTTP status code in an ASP.NET Core Web API, we can use several approaches depending on the context of our API method. The 200 HTTP status code signifies a successful request, and it’s commonly used when data is being returned to the client. That means the HTTP 200 Status code indicates that the request is successful.

Returning Ok():

The OK() method is a convenient way to return a 200 OK status code. When you want to return data, you can pass the data as an argument to this method. This approach automatically serializes the data to JSON (or XML, based on the request’s Accept header) and sets the content type of the response.

ASP.NET Core provided the OK method to return the HTTP 200 Status Code. If you check the ControllerBase class, you will find two overloaded versions of the OK method, as shown below.

How to Return 200 HTTP Status Code in ASP.NET Core Web API?

The first overloaded version, which does not take any input parameter, will create an object that produces an empty HTTP 200 OK Status code as a response. On the other hand, the second overloaded version takes an object (any value) as input and creates an object that produces HTTP 200 OK Status code as a response. The input data it takes will be formatted in the response body.

Further, if you notice, the first overloaded version of the OK method returns OKResult. Now, right-click on the OkResult and choose to go to definition, and you will see the following definition.

How to Return 200 HTTP Status Code in ASP.NET Core Web API?

As you can see, the OKResult set the DefaultStatusCode value to 200. As you can see in the above image, this method is inherited from the StatusCodeResult class. Further, if you right-click on the StatusCodeResult class and choose to go to the definition, then you will find the following definition.

Returning Ok()

The StatusCodeResult class is inherited from ActionResult and IActionResult. So, you can use IActionResult as the return type for the OK method. The StatusCodeResult class has the StatusCode property, and using this property, you can set the proper status code.

Further, if you notice, the second overloaded version of the OK method returns OkObjectResult. Now, right-click on the OkObjectResult class and choose to go to definition, and you will see the following definition.

OkObjectResult

As you can see, the OkObjectResult class is inherited from the ObjectResult class. Now, again, right-click in the ObjectResult class and choose to go to definition, and you will find the following definition of the ObjectResult class.

ObjectResult

If you notice here, the ObjectResult class is inherited from ActionResult. So, you can use ActionResult or IActionResult as the return type for the second overloaded version of the OK method. Further, if you notice the ObjectResult class has the StatusCode property, you can set the proper status code using this property. 

Returning 200 HTTP Status Code Without Data:

In this case, we have to use the first overloaded version of the OK method, which does not take any parameters. So, please modify the Employee Controller as shown below.

using Microsoft.AspNetCore.Mvc;
namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpGet("GetEmployees")]
        public IActionResult GetEmployees()
        {
            //Do Some Operation
            return Ok();
        }
    }
}

Run the application and issue a GET request to the URL api/employee/getemployees using Postman, as shown in the image below. As you can see, once you hit the Send button, you will get a 200 OK Status code without any data in the response body.

Returning 200 HTTP Status Code Without Data

Creating Employee Model:

We are going to use the following model to return data from the controller action method. So, create a class file named Employee.cs and then copy and paste the following code into it:

namespace ReturnTypeAndStatusCodes.Models
{
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public string City { get; set; }
        public int Age { get; set; }
        public string Department { get; set; }
    }
}
Returning 200 HTTP Status Code with Data:

In this case, we have to use the second overloaded version of the OK method, which takes an object as an input parameter. So, please modify the Employee Controller class as shown below. Here, we are returning the list of employees from the action method. As the OK method takes object type, we can pass any data. Here, I am passing the list of employees to the OK method.

using ReturnTypeAndStatusCodes.Models;
using Microsoft.AspNetCore.Mvc;
namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpGet("GetEmployees")]
        public ActionResult<List<Employee>> GetEmployees()
        {
            var listEmployees = new List<Employee>()
            {
                new Employee(){ Id = 1001, Name = "Anurag", Age = 28, City = "Mumbai", Gender = "Male", Department = "IT" },
                new Employee(){ Id = 1002, Name = "Pranaya", Age = 28, City = "Delhi", Gender = "Male", Department = "IT" },
                new Employee(){ Id = 1003, Name = "Priyanka", Age = 27, City = "BBSR", Gender = "Female", Department = "HR"},
            };

            return Ok(listEmployees);
        }
    }
}

Now save the changes, run the application, and issue a GET request to the same URL api/employee/getemployees using Postman, as shown in the image below. Now, you can see that once you hit the Send button, you will get a 200 OK Status code with the employee data in the response body in JSON format.

Returning 200 HTTP Status Code with Data

The OK Method is very helpful for GET-type requests. For example, get all Employees data, get single employee data, get employee data based on some search parameters, etc.

Returning OkObjectResult Directly

You can also return an instance of OkObjectResult directly. This is useful when you want to control the instantiation explicitly or when returning from services or helpers that are not aware of the ControllerBase context.

using ReturnTypeAndStatusCodes.Models;
using Microsoft.AspNetCore.Mvc;
namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpGet("GetEmployees")]
        public ActionResult<List<Employee>> GetEmployees()
        {
            var listEmployees = new List<Employee>()
            {
                new Employee(){ Id = 1001, Name = "Anurag", Age = 28, City = "Mumbai", Gender = "Male", Department = "IT" },
                new Employee(){ Id = 1002, Name = "Pranaya", Age = 28, City = "Delhi", Gender = "Male", Department = "IT" },
                new Employee(){ Id = 1003, Name = "Priyanka", Age = 27, City = "BBSR", Gender = "Female", Department = "HR"},
            };

            return new OkObjectResult(listEmployees); // Equivalent to Ok(listEmployees)
        }
    }
}
Manual Status Code Setting in ASP.NET Core Web API

Though not common for a 200 OK scenario, you can manually set the response status code using the StatusCode method. This approach can be used to return any type of Status Code with or without data in ASP.NET Core Web API.

using ReturnTypeAndStatusCodes.Models;
using Microsoft.AspNetCore.Mvc;
namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpGet("GetEmployees")]
        public ActionResult<List<Employee>> GetEmployees()
        {
            var listEmployees = new List<Employee>()
            {
                new Employee(){ Id = 1001, Name = "Anurag", Age = 28, City = "Mumbai", Gender = "Male", Department = "IT" },
                new Employee(){ Id = 1002, Name = "Pranaya", Age = 28, City = "Delhi", Gender = "Male", Department = "IT" },
                new Employee(){ Id = 1003, Name = "Priyanka", Age = 27, City = "BBSR", Gender = "Female", Department = "HR"},
            };

            return StatusCode(200, listEmployees); // Manually setting 200 OK
        }
    }
}
200 HTTP Status Code Real-Time Examples in ASP.NET Core Web API

In ASP.NET Core Web API, the HTTP 200 OK status code is typically used to indicate that a request has been successfully processed. For various operations like GET, POST, PUT, or DELETE, the API might return a 200 Status Code, possibly along with data. For this demo, let us first modify the Employee model as follows:

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; }
    }
}
Modifying the Employee Controller:

Please modify the Employee Controller as follows. Here, we are performing the CRUD operation.

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" },
        };

        //URL: GET /api/employee
        [HttpGet]
        public ActionResult<Employee> GetAllEmployees()
        {
            // 200 OK with all the employees in the response body
            return Ok(Employees);
        }

        //URL: GET /api/employee/1
        [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); 
        }

        //URL:POST /api/employee
        [HttpPost]
        public ActionResult<Employee> CreateOrUpdateEmployee(Employee employee)
        {
            var existingEmployee = Employees.FirstOrDefault(emp => emp.Id == employee.Id);
            if (existingEmployee != null)
            {
                // Update the existing employee
                existingEmployee.Name = employee.Name;
                existingEmployee.Age = employee.Age;
                existingEmployee.Gender = employee.Gender;
                employee.Department = employee.Department;

                // 200 OK with the updated employee
                return Ok(existingEmployee); 
            }
            else
            {
                // Add a new employee
                employee.Id = Employees.Count() + 1;
                Employees.Add(employee); 
                return CreatedAtAction(nameof(GetEmployee), new { id = employee.Id }, employee);
            }
        }

        //URL:PUT /api/employee/1
        [HttpPut("{id}")]
        public ActionResult<Employee> UpdateEmployee(int id, Employee employee)
        {
            if (id != employee.Id)
            {
                // 400 Bad Request if the ID does not match
                return BadRequest();
            }

            var existingEmployee = Employees.FirstOrDefault(emp => emp.Id == employee.Id);
            if (existingEmployee == null)
            {
                // 404 Not Found if the employee does not exist
                return NotFound(); 
            }

            // Update the existing employee
            existingEmployee.Name = employee.Name;
            existingEmployee.Age = employee.Age;
            existingEmployee.Gender = employee.Gender;
            employee.Department = employee.Department;

            // 200 OK with the updated employee
            return Ok(existingEmployee); 
        }

        //URL:DELETE /api/employee/1
        [HttpDelete("{id}")]
        public ActionResult<Employee> DeleteEmployee(int id)
        {
            var employee = Employees.FirstOrDefault(emp => emp.Id == id);
            if (employee == null)
            {
                // 404 Not Found if the employee does not exist
                return NotFound(); 
            }

            // Delete the employee
            Employees.Remove(employee); 
            return Ok(employee); // 200 OK with the deleted employee's details
        }
    }
}

In the above example:

  • Returning 200 OK for a GET Request: A GET request retrieves data. The 200 OK Response often includes the requested data in the body.
  • Returning 200 OK for a POST Request: Although it’s more common to return a 201 Created for a POST request, there are scenarios where you might want to return 200 OK, especially if the operation is idempotent and the resource already exists.
  • Returning 200 OK for a PUT Request: A PUT request is typically used for updating resources. A 200 OK response indicates that the update was successful.
  • Returning 200 OK for a DELETE Request: While a 204 No Content response is commonly used for DELETE operations to indicate success without returning any content, you can also use 200 OK if you want to return information about the deleted resource.
Testing the APIs:

You can test the APIs in many ways, like using Postman, Fiddler, and Swagger. But .NET 8 provides the .http file, and using that .http file, we can also test the functionality very easily. This .http file name will be the same as your project name. So, open the .http file and copy and paste the following code. Please change the port number with the port number on which your application is running.

@MyFirstWebAPIProject_HostAddress = https://localhost:7128

### Get All Employees
GET {{MyFirstWebAPIProject_HostAddress}}/api/employee
Accept: application/json
###

### Get Employee with ID 1
GET {{MyFirstWebAPIProject_HostAddress}}/api/employee/1
Accept: application/json
###

### Create a New Employee
POST {{MyFirstWebAPIProject_HostAddress}}/api/employee
Content-Type: application/json

{
  "name": "Suresh",
  "gender": "Male",
  "age": 35,
  "department": "HR"
}

###

### Update Employee with ID 1
PUT {{MyFirstWebAPIProject_HostAddress}}/api/employee/1
Content-Type: application/json

{
    "Id": 1,
    "name": "Suresh",
    "gender": "Male",
    "age": 35,
    "department": "HR"
}

###

### Delete Employee with ID 1
DELETE {{MyFirstWebAPIProject_HostAddress}}/api/employee/1
###
Using IActionResult and ActionResult as the Return Type:

Instead of using ActionResult<T> as the return type, we can also use ActionResult or IActionResult as the return type. In that case, the swagger API will not give any information about the response data. So, please modify the Employee Controller as follows. Here, you can see that for some of the APIs, I am using IActionResult, and for some other APIs, I am using ActionResult as the return type.

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" },
        };

        //URL: GET /api/employee
        [HttpGet]
        public ActionResult GetAllEmployees()
        {
            // 200 OK with all the employees in the response body
            return Ok(Employees);
        }

        //URL: GET /api/employee/1
        [HttpGet("{id}")]
        public ActionResult 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); 
        }

        //URL:POST /api/employee
        [HttpPost]
        public IActionResult CreateOrUpdateEmployee(Employee employee)
        {
            var existingEmployee = Employees.FirstOrDefault(emp => emp.Id == employee.Id);
            if (existingEmployee != null)
            {
                // Update the existing employee
                existingEmployee.Name = employee.Name;
                existingEmployee.Age = employee.Age;
                existingEmployee.Gender = employee.Gender;
                employee.Department = employee.Department;

                // 200 OK with the updated employee
                return Ok(existingEmployee); 
            }
            else
            {
                // Add a new employee
                employee.Id = Employees.Count() + 1;
                Employees.Add(employee); 
                return CreatedAtAction(nameof(GetEmployee), new { id = employee.Id }, employee);
            }
        }

        //URL:PUT /api/employee/1
        [HttpPut("{id}")]
        public IActionResult UpdateEmployee(int id, Employee employee)
        {
            if (id != employee.Id)
            {
                // 400 Bad Request if the ID does not match
                return BadRequest();
            }

            var existingEmployee = Employees.FirstOrDefault(emp => emp.Id == employee.Id);
            if (existingEmployee == null)
            {
                // 404 Not Found if the employee does not exist
                return NotFound(); 
            }

            // Update the existing employee
            existingEmployee.Name = employee.Name;
            existingEmployee.Age = employee.Age;
            existingEmployee.Gender = employee.Gender;
            employee.Department = employee.Department;

            // 200 OK with the updated employee
            return Ok(existingEmployee); 
        }

        //URL:DELETE /api/employee/1
        [HttpDelete("{id}")]
        public ActionResult<Employee> DeleteEmployee(int id)
        {
            var employee = Employees.FirstOrDefault(emp => emp.Id == id);
            if (employee == null)
            {
                // 404 Not Found if the employee does not exist
                return NotFound(); 
            }

            // Delete the employee
            Employees.Remove(employee); 
            return Ok(employee); // 200 OK with the deleted employee's details
        }
    }
}

Now, run the application and test the APIs; it should work as expected. Now, if you want, you can also make these APIs asynchronous. In this case, if your APIs are doing IO-bound operations, it will not block the thread executing your application 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" },
        };

        //URL: GET /api/employee
        [HttpGet]
        public async Task<ActionResult> GetAllEmployees()
        {
            //Do Some IO Bound Operation 
            //Delaying the Execution for 1000 MS
            await Task.Delay(TimeSpan.FromMilliseconds(1000));
            // 200 OK with all the employees in the response body
            return Ok(Employees);
        }

        //URL: GET /api/employee/1
        [HttpGet("{id}")]
        public async Task<ActionResult<Employee>> GetEmployee(int id)
        {
            //Do Some IO Bound Operation 
            //Delaying the Execution for 1000 MS
            await Task.Delay(TimeSpan.FromMilliseconds(1000));

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

        //URL:POST /api/employee
        [HttpPost]
        public async Task<IActionResult> CreateOrUpdateEmployee(Employee employee)
        {
            //Do Some IO Bound Operation 
            //Delaying the Execution for 1000 MS
            await Task.Delay(TimeSpan.FromMilliseconds(1000));

            var existingEmployee = Employees.FirstOrDefault(emp => emp.Id == employee.Id);
            if (existingEmployee != null)
            {
                // Update the existing employee
                existingEmployee.Name = employee.Name;
                existingEmployee.Age = employee.Age;
                existingEmployee.Gender = employee.Gender;
                employee.Department = employee.Department;

                // 200 OK with the updated employee
                return Ok(existingEmployee); 
            }
            else
            {
                // Add a new employee
                employee.Id = Employees.Count() + 1;
                Employees.Add(employee); 
                return CreatedAtAction(nameof(GetEmployee), new { id = employee.Id }, employee);
            }
        }

        //URL:PUT /api/employee/1
        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateEmployee(int id, Employee employee)
        {
            //Do Some IO Bound Operation 
            //Delaying the Execution for 1000 MS
            await Task.Delay(TimeSpan.FromMilliseconds(1000));

            if (id != employee.Id)
            {
                // 400 Bad Request if the ID does not match
                return BadRequest();
            }

            var existingEmployee = Employees.FirstOrDefault(emp => emp.Id == employee.Id);
            if (existingEmployee == null)
            {
                // 404 Not Found if the employee does not exist
                return NotFound(); 
            }

            // Update the existing employee
            existingEmployee.Name = employee.Name;
            existingEmployee.Age = employee.Age;
            existingEmployee.Gender = employee.Gender;
            employee.Department = employee.Department;

            // 200 OK with the updated employee
            return Ok(existingEmployee); 
        }

        //URL:DELETE /api/employee/1
        [HttpDelete("{id}")]
        public ActionResult<Employee> DeleteEmployee(int id)
        {
            var employee = Employees.FirstOrDefault(emp => emp.Id == id);
            if (employee == null)
            {
                // 404 Not Found if the employee does not exist
                return NotFound(); 
            }

            // Delete the employee
            Employees.Remove(employee); 
            return Ok(employee); // 200 OK with the deleted employee's details
        }
    }
} 
When to Return 200 HTTP Status Code in ASP.NET Core Web API?

In ASP.NET Core Web API, returning a 200 HTTP status code is appropriate in several scenarios, primarily indicating that a request has succeeded. The HTTP 200 status code is the most generic success status code, signaling that the request was received, understood, and processed. Here are specific situations in which returning a 200 OK status might be suitable:

  • Retrieving Resources: When a client makes a GET request to retrieve data, such as fetching a list of items or a specific item detail, the data is successfully found and returned.
  • Updating Resources: After a PUT or PATCH request has successfully updated an existing resource without any side effects that the client needs to be aware of. It indicates that the requested changes have been applied.
  • Deleting Resources: Following a DELETE request if the resource has been successfully removed. However, some prefer to use 204 No Content to indicate successful deletion when there’s no additional content to send in the response body.
  • General Success: For any general API operations completed successfully, the client expects some data in response. For example, a POST request that creates a resource might return 201 along with the newly created resource’s details, but if the operation is something else that doesn’t involve creating a new resource, 200 OK might be more appropriate if there’s data to return.
  • Custom Actions: Custom actions in your API that don’t necessarily create, update, or delete resources but perform some operations and return data or confirmation of success.

It’s important to note that while 200 OK is suitable for many successful operations, other success status codes can provide more specific information about the request’s outcome:

  • 201 Created: Specifically, for when a new resource has been successfully created.
  • 202 Accepted: Indicates that the request has been accepted for processing but has not been completed.
  • 204 No Content: Indicates that the server successfully processed the request but is not returning any content. Often used for DELETE operations or when PUT operations do not return any content.

In the next article, I will discuss How to Return 201 HTTP Status Code in ASP.NET Core Web API with Examples. In this article, I try to explain How to Return 200 OK HTTP Status Code from ASP.NET Core Web API with Examples, and I hope you enjoy this article on “200 HTTP Status Codes in the ASP.NET Core Web API”.

Leave a Reply

Your email address will not be published. Required fields are marked *