400 HTTP Status Code in ASP.NET Core Web API

400 HTTP Status Code in ASP.NET Core Web API

In this article, I will discuss How to Return 400 Bad Request HTTP Status Code from the ASP.NET Core Web API Controller Action method with Examples. Please read our previous article discussing How to Return 302 HTTP Status Code in ASP.NET Core Web API with Examples.

400 HTTP Status Code

The 400 HTTP Status Code indicates that the request sent to the server by the client was somehow incorrect or corrupted, and the server couldn’t understand it. The 400 Status Code belongs to the 4xx class of status codes, which are used for indicating client errors. The 400 Status Code means “Bad Request.” It is a generic error response indicating that the server cannot process the request due to client error. Common causes for a 400 Bad Request error can include:

  • Incorrectly formatted URL.
  • Invalid or missing request parameters.
  • Malformed request headers.
  • Payloads that are too large.
  • Syntax errors in the request body (e.g., invalid JSON or XML).

To resolve a 400 Bad Request error, the client should:

  • Verify the syntax of the request URL.
  • Check that the request adheres to the expected format, including headers, query parameters, and the request body.
  • Ensure that the size of the request payload is within the server’s accepted limits.
  • Correct any data formatting issues (such as JSON, XML, etc.) in the request body.

When developing web applications, it’s important for developers to handle 400 errors. This might involve providing informative error messages to the user or logging detailed information for debugging purposes.

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

In the context of an ASP.NET Core Web API, this response typically means that the data sent by the client to the server did not follow the expected format or was in some way incorrect according to the API’s expectations. Handling and returning a 400 Bad Request status in an ASP.NET Core Web API can be managed in several ways, depending on the specific circumstances of the error.

Using BadRequest Method

The simplest way to return a 400 Status Code is by using the BadRequest method available in the ControllerBase class. This method is useful when you want to indicate that something is wrong with the client’s request.

Let us understand this with an example. First, create the following Employee class within the Models folder. By default, all the properties of the following Employee model are mandatory or required. If a property is a nullable type, then it is optional. Else, it is mandatory. Here, we are not creating any property as a nullable type by putting the question mark.

using System.ComponentModel.DataAnnotations;

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

Next, modify the Employee Controller as follows. Here, you can see within the CreateEmployee method, we are checking the Model state and if it is not valid, then we are returning 400 Bad Request HTTP Status Response Code to the client.

using Microsoft.AspNetCore.Mvc;
using ReturnTypeAndStatusCodes.Models;

namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpPost]
        public IActionResult CreateEmployee([FromBody] Employee employee)
        {
            if (!ModelState.IsValid)
            {
                // Returns a 400 Status Code with model state errors
                return BadRequest(ModelState); 
            }

            // Process the request...

            // Returns a 200 Status Code indicating success
            return Ok(); 
        }
    }
}
Testing the API:

URL: https://localhost:7094/api/Employee

Method: POST

Request Body: Here, I am not passing the Name, City, and Gender required field values in the request body.

{
  "id": 1,
  "age": 25,
  "department": "IT"
}

So, open Postman, provide the above details and click on the Send button, as shown in the below image, which will send a Post request to the server. Please change the port number where your application is running.

400 HTTP Status Code in ASP.NET Core Web API

Once you click on the Send button, you will get the following response.

400 HTTP Status Code in ASP.NET Core Web API

As you can see in the above image, the response body shows all the details about an error with the status code 400. When we encounter a 400 Bad Request response, it typically includes several pieces of information to help diagnose the issue:

  • Type: This refers to the type of error encountered. In the context of ASP.NET Core, it’s often a URI that identifies a specific problem type, conforming to the format defined by RFC 7807 for Problem Details for HTTP APIs.
  • Title: A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem except for purposes of localization.
  • TraceId: This is a unique identifier for the request, which can be used to trace the request in the logs. ASP.NET Core automatically generates and includes a TraceId in responses if logging and diagnostics are correctly configured in the application.
  • Status: The HTTP status code generated by the server. In this case, it would be 400.
  • Errors: A more detailed explanation of what caused the request to fail. This could be validation errors, missing fields, or data that does not meet the API’s requirements.

Note: ASP.NET Core automatically converts certain types of errors into ProblemDetails responses. This feature is especially useful for handling validation errors. Ensure you have the [ApiController] attribute at the class level. This attribute enables automatic model validation and response formatting according to the ProblemDetails format.

Returning BadRequestObjectResult Directly

You can also directly instantiate and return a BadRequestObjectResult object. This approach gives you a bit more control over the response. Please comment on the ApiController attribute to work this correctly. Otherwise, before executing the action method, ApiController will check the model, and if it is found invalid, it will return the default Bad Request error response.

using Microsoft.AspNetCore.Mvc;
using ReturnTypeAndStatusCodes.Models;

namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    //[ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpPost]
        public IActionResult CreateEmployee([FromBody] Employee employee)
        {
            if (!ModelState.IsValid)
            {
                var errorResponse = new { Error = "Invalid Data Provided" };
                // Returns a 400 status code with a custom error object
                return new BadRequestObjectResult(errorResponse); 
            }

            // Process the request...

            // Returns a 200 Status Code indicating success
            return Ok(); 
        }
    }
}
Problem Details for API Errors

ASP.NET Core supports the use of the ProblemDetails object as part of RFC 7807, which provides a standardized way to convey error details in HTTP responses. This can be used to provide more detailed information about what went wrong. The ProblemDetails object includes several properties that you can set to provide detailed error information:

  • Type: A URI reference that identifies the problem type. This is intended to be dereferenced by the client to obtain detailed information about the problem type.
  • Title: A short, human-readable summary of the problem type.
  • Status: The HTTP status code generated by the server for this occurrence of the problem.
  • Detail: A human-readable explanation specific to this occurrence of the problem.
  • Instance: A URI reference that identifies the specific occurrence of the problem.

For a better understanding, please modify the Employee Controller as follows. Please comment on the ApiController attribute to work this correctly.

using Microsoft.AspNetCore.Mvc;
using ReturnTypeAndStatusCodes.Models;
using System.Diagnostics;

namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    //[ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpPost]
        public IActionResult CreateEmployee([FromBody] Employee employee)
        {
            if (!ModelState.IsValid)
            {
                // Returns a 400 Status Code with model state errors
                var problemDetails = new ProblemDetails()
                { 
                    Title = "Validation Errors Occurred.", 
                    Detail = "See the Errors Property for Details.",
                    Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1",
                    Status = StatusCodes.Status400BadRequest,
                    Instance = HttpContext.Request.Path,
                    Extensions = { { "traceId", Activity.Current?.Id ?? HttpContext.TraceIdentifier } }
                };
                return BadRequest(problemDetails);
            }

            // Process the request...

            // Returns a 200 Status Code indicating success
            return Ok(); 
        }
    }
}
Response:

Problem Details for API Errors

Using ValidationProblemDetails Object

ASP.NET Core supports the use of the ValidationProblemDetails object as part of RFC 7807, which provides a standardized way to convey error details in HTTP responses. ValidationProblemDetails is a subclass of ProblemDetails specifically designed for returning validation errors. It automatically populates the Errors property with the validation errors from ModelState. Please comment on the ApiController attribute to work this correctly.

using Microsoft.AspNetCore.Mvc;
using ReturnTypeAndStatusCodes.Models;

namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    //[ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpPost]
        public IActionResult CreateEmployee([FromBody] Employee employee)
        {
            if (!ModelState.IsValid)
            {
                // Returns a 400 Status Code with model state errors
                var problemDetails = new ValidationProblemDetails(ModelState)
                { 
                    Title = "Validation errors occurred.", 
                    Detail = "See the errors property for details.",
                    Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1",
                    Status = StatusCodes.Status400BadRequest,
                    Instance = HttpContext.Request.Path
                };
                return BadRequest(problemDetails);
            }

            // Process the request...

            // Returns a 200 Status Code indicating success
            return Ok(); 
        }
    }
}
Response:

Using ValidationProblemDetails Object

Manual 400 HTTP Response in ASP.NET Core Web API

In some cases, you might need more control over the response. You can manually set the status code of the HttpResponse object. For a better understanding, please modify the Employee Controller as follows:

using Microsoft.AspNetCore.Mvc;
using ReturnTypeAndStatusCodes.Models;

namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    //[ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpPost]
        public IActionResult CreateEmployee([FromBody] Employee employee)
        {
            if (!ModelState.IsValid)
            {
                // Manually setting the status code to 400
                Response.StatusCode = 400;

                // You can still return a body
                return new ObjectResult(new { Error = "Invalid data provided" }); 
            }

            // Process the request...

            // Returns a 200 Status Code indicating success
            return Ok(); 
        }
    }
}
400 HTTP Status Code Real-Time Examples in ASP.NET Core Web API

Below are real-time examples and scenarios where an ASP.NET Core Web API might return a 400 Status Code:

Validation Failures

When the client submits a request with data that fails server-side validation rules, this can include missing required fields, providing data in an incorrect format, or any other validation constraints defined by the API. When input validation fails for a request, it’s a common practice to return a 400 Status Code. ASP.NET Core utilizes data annotations and model validation to enforce input validation rules automatically.

[HttpPost]
public IActionResult CreateEmployee([FromBody] Employee employee)
{
    if (!ModelState.IsValid)
    {
        // Returns 400 with validation errors
        return BadRequest(ModelState);
    }

    // Process the valid product...

    // Returns a 200 Status Code indicating success
    return Ok();
}
Malformed JSON

If the request body contains JSON that is malformed or cannot be parsed, the API should return a 400 Status Code. ASP.NET Core automatically handles this scenario if you are using the [FromBody] attribute and the JSON cannot be deserialized into the target model.

A client sends a request with a body containing invalid JSON (e.g., missing a closing brace). The ASP.NET Core framework’s model binding will fail, and it will automatically return a 400 Status Code. The following JSON will cause 400 Bad Request. After the second key-value pair, we are missing the comma (,).

{
  "id": 1,
  "age": 25
  "department": "IT"
}
Response:

400 HTTP Status Code Real-Time Examples in ASP.NET Core Web API

Missing Required Parameters

When a request is missing required parameters, either in the URL or the body, returning a 400 Status Code is appropriate to indicate that the request cannot be processed due to incomplete information.

[HttpGet]
public IActionResult GetUserInfo([FromQuery] string EmployeeId)
{
    if (string.IsNullOrEmpty(EmployeeId))
    {
        return BadRequest("EmployeeId is required.");
    }
    // Retrieve and return user information...

    // Returns a 200 Status Code indicating success
    return Ok();
}
Invalid Query Strings

When query string parameters are provided but are invalid (e.g., wrong format, out-of-range values), the API should respond with a 400 Status Code.

[HttpGet]
public IActionResult GetOrders([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
{
    if (endDate < startDate)
    {
        return BadRequest("EndDate must be greater than StartDate.");
    }
    // Retrieve and return orders...

    // Returns a 200 Status Code indicating success
    return Ok();
}

In the next article, I will discuss How to Return 401 HTTP Status Code in ASP.NET Core Web API with Examples. In this article, I try to explain How to Return 400 Bad Request HTTP Status Code in ASP.NET Core Web API with Examples, and I hope you enjoy this article on “400 Bad Request HTTP Status Code in the ASP.NET Core Web API”.

Leave a Reply

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