2XX HTTP Status Codes in ASP.NET Core Web API

2XX HTTP Status Codes in ASP.NET Core Web API

In this article, I will explain 2XX HTTP Status Codes in ASP.NET Core Web API Application with examples. Please read our previous article discussing 1XX HTTP Status Codes in ASP.NET Core Web API Applications.

2XX HTTP Status Codes in ASP.NET Core Web API

In ASP.NET Core Web API, HTTP status codes play an important role in communicating the result of client requests to the server. The 2xx HTTP status codes indicate that the server successfully received, understood, and processed a client’s request. This response is further refined by specific status codes within the 2xx range to provide more detailed information. Let us know the meaning of each 2XX HTTP Status code and its meaning, as well as when to use which one.

  • 200 OK
  • 201 Created
  • 202 Accepted
  • 204 No Content

200 OK HTTP Status Code:

The 200 OK HTTP Status Code indicates that the request was successful and the server has returned the requested data (if applicable). This is the most common HTTP Status Code, and the meaning of “SUCCESS” varies depending on the HTTP method:

  • GET: The resource has been fetched and is transmitted in the message body.
  • POST: The resource describing the result of the action is transmitted in the message body.
  • PUT, DELETE: The resource was successfully processed, and the response body contains an entity describing the status.

For example, fetching a list of users, creating a new user, or updating an existing record without returning extra information. We need to use HTTP Status code when a resource is successfully retrieved, updated, or deleted, and the response includes an entity describing the status or result. The following is the syntax to return 200 OK HTTP Status Code in ASP.NET Core Web API.

return Ok(data); // For returning data in response

201 Created HTTP Status Code:

201 Created HTTP Status Code indicate that the request was successful, and a new resource was created. It is used primarily in POST methods when a new resource is created, and the response should include a Location header that contains the URL of the newly created resource. The following is the syntax to return 201 Created HTTP Status Code in ASP.NET Core Web API.

return CreatedAtAction(nameof(GetById), new { id = newResource.Id }, newResource);

202 Accepted HTTP Status Code:

202 Accepted HTTP status code indicates that the request has been accepted for processing, but the processing has not been completed. It is useful for asynchronous tasks that have been started but has not yet been completed. It informs the client that the request is being processed, though no immediate result is available.

It is typically used when the server has accepted a request that might take some time to process, such as a request that triggers a long-running background task or batch processing. The following syntax is to return the 202 Accepted HTTP Status Code in ASP.NET Core Web API.

return AcceptedAtAction(); // For asynchronous request accepted for processing

204 No Content HTTP Status Code:

The 204 No Content status code indicates that the server successfully processed the request but is not returning any content. It is typically used in API responses where the result does not need to return data to the client, such as when a DELETE request is successful, or for PUT/PATCH requests that don’t require returning a response body (like updates that don’t need a confirmation message). The following syntax is to return the 202 Accepted HTTP Status Code in ASP.NET Core Web API.

return NoContent(); // For successful delete or update without content

Example to Understand 2XX HTTP Status Codes in ASP.NET Core Web API:

Let us understand the 2XX HTTP Status Codes with one example, i.e., Product Management API. We will create one ASP.NET Core Web API controller named ProductsController demonstrating the usage of the 2XX HTTP status codes. Here, we are also going to use SQL Server as the database and EF Core as the data access technology to perform the database operations.

First, create a new ASP.NET Core Web API project named HTTPStatusCodeDemo. To integrate EF Core with SQL Server, we need to install the following NuGet packages.

  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools

So, please open the Package Manager Console in Visual Studio and execute the following commands to install these packages:

  • Install-Package Microsoft.EntityFrameworkCore.SqlServer
  • Install-Package Microsoft.EntityFrameworkCore.Tools
Creating Product Model:

So, first, create a folder named Models at the project root directory and then create a class file named Product.cs within the Models folder and then copy and paste the following code:

using System.ComponentModel.DataAnnotations.Schema;
namespace HTTPStatusCodeDemo.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [Column(TypeName ="decimal(18,2)")]
        public decimal Price { get; set; }
        public string? Description { get; set; }
    }
}

The Product model represents the structure of a product entity within the application. This class includes properties such as ID, Name, Price, and an optional Description. It serves as the primary data structure for storing and manipulating product information.

Creating Processing Status Model:

Create a class file named ProcessingStatus.cs within the Models folder, and copy and paste the following code. This model is used to return the current status of a long-running task.

namespace HTTPStatusCodeDemo.Models
{
    public class ProcessingStatus
    {
        public int Id { get; set; }
        public string OperationId { get; set; }
        public string Status { get; set; }
    }
}
Creating DTOs:

Next, create a folder named DTOs at the project root directory where we will create all our DTOs used to transfer the data between client and server.

ProductCreateDTO

Create a class file named ProductCreateDTO.cs within the DTOs folder, and then copy and paste the following code.

namespace HTTPStatusCodeDemo.DTOs
{
    public class ProductCreateDTO
    {
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string? Description { get; set; }
    }
}

This ProductCreateDTO (Data Transfer Object) is used when creating a new product. This DTO encapsulates the data required from the client to create a product, excluding the ID, which is typically generated by the server. It ensures that only relevant data is received during the creation process.

ProductUpdateDTO

Create a class file named ProductUpdateDTO.cs within the DTOs folder and then copy and paste the following code.

namespace HTTPStatusCodeDemo.DTOs
{
    public class ProductUpdateDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string? Description { get; set; }
    }
}

This ProductUpdateDTO is used to update an existing product. Similar to ProductCreateDTO, this DTO contains the fields that can be updated (Name, Price, Description) but excludes the Id. It facilitates the transfer of updated data from the client to the server.

ProcessingStatusDTO

Create a class file named ProcessingStatusDTO.cs within the DTOs folder, and then copy and paste the following code.

namespace HTTPStatusCodeDemo.DTOs
{
    public class ProcessingStatusDTO
    {
        public int Id { get; set; }
        public string OperationId { get; set; }
        public string Status { get; set; }
    }
}

The ProcessingStatusDTO is used to represent the status of long-running or asynchronous processing operations. It includes an Id and OperationId to uniquely identify the operation and a Status string to indicate the current state (e.g., “Processing”, “Completed”). This DTO helps in tracking and communicating the progress of asynchronous tasks to the client.

ErrorResponseDTO

A standardized DTO to represent error responses. This ensures that all error messages follow a consistent structure, making it easier for clients to parse and handle errors. So, create a class file named ErrorResponseDTO.cs within the DTOs folder and copy and paste the following code.

namespace HTTPStatusCodeDemo.DTOs
{
    public class ErrorResponseDTO
    {
        public int StatusCode { get; set; }
        public string Message { get; set; }
        public string? ErrorDetails { get; set; }

        public ErrorResponseDTO(int statusCode, string message, string? errorDetails = null)
        {
            StatusCode = statusCode;
            Message = message;
            ErrorDetails = errorDetails;
        }
    }
}

The ErrorResponseDTO is used to standardize error responses across the API. This DTO includes the StatusCode, a user-friendly Message, and optional ErrorDetails for more detailed error information. It ensures consistency in communicating errors to clients, making it easier for them to handle and display error messages appropriately.

Create the Application Db Context

Create a new folder named Data at the project root. Within this folder, add a new class file named ApplicationDbContext.cs, and then copy and paste the following code.

using HTTPStatusCodeDemo.Models;
using Microsoft.EntityFrameworkCore;

namespace HTTPStatusCodeDemo.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // Seed initial data for Products
            modelBuilder.Entity<Product>().HasData(
                new Product { Id = 1, Name = "Laptop", Price = 999.99M, Description = "High-performance laptop" },
                new Product { Id = 2, Name = "Smartphone", Price = 499.99M, Description = "Latest model smartphone" },
                new Product { Id = 3, Name = "Headphones", Price = 199.99M, Description = "Noise-cancelling headphones" }
            );

            // Seed initial data for ProcessingStatus
            modelBuilder.Entity<ProcessingStatus>().HasData(
                new ProcessingStatus { Id = 1, OperationId = "a541e31b-9560-4977-b3a7-dc19afb21875", Status = "Processing" },
                new ProcessingStatus { Id = 2, OperationId = "0749e846-fb51-420b-abc9-47888151f528", Status = "Completed" }
            );
        }
        // DbSet for Products
        public DbSet<Product> Products { get; set; }

        // DbSet for ProcessingStatus 
        public DbSet<ProcessingStatus> ProcessingStatuses { get; set; }
    }
}
Configure the Connection String

Add the SQL Server connection string to the appsettings.json file. So, please modify the appsettings.json file as follows.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=LAPTOP-6P5NK25R\\SQLSERVER2022DEV;Database=ProductsDB;Trusted_Connection=True;TrustServerCertificate=True;"
  }
}
Creating Product Service:

Next, create a folder named Services at the project root directory, create a class file named ProductService.cs within the Services folder, and copy and paste the following code.

using HTTPStatusCodeDemo.Data;
using HTTPStatusCodeDemo.DTOs;
using HTTPStatusCodeDemo.Models;
using Microsoft.EntityFrameworkCore;

namespace HTTPStatusCodeDemo.Services
{
    public class ProductService
    {
        private readonly ApplicationDbContext _context;

        // Constructor injection of the DbContext
        public ProductService(ApplicationDbContext context)
        {
            _context = context;
        }

        // Retrieves a product by its ID
        public async Task<Product?> GetProductByIdAsync(int id)
        {
            return await _context.Products.FindAsync(id);
        }

        // Retrieves all products
        public async Task<IEnumerable<Product>> GetAllProductsAsync()
        {
            return await _context.Products.OrderBy(p => p.Id).ToListAsync();
        }

        // Creates a new product
        public async Task<Product> CreateProductAsync(ProductCreateDTO productDto)
        {
            var product = new Product
            {
                Name = productDto.Name,
                Price = productDto.Price,
                Description = productDto.Description,
            };

            _context.Products.Add(product);
            await _context.SaveChangesAsync();

            return product;
        }

        // Updates an existing product
        public async Task<Product?> UpdateProductAsync(int id, ProductUpdateDTO productDto)
        {
            var existingProduct = await _context.Products.FindAsync(id);
            if (existingProduct == null)
            {
                return null;
            }

            existingProduct.Name = productDto.Name;
            existingProduct.Price = productDto.Price;
            existingProduct.Description = productDto.Description;

            await _context.SaveChangesAsync();

            return existingProduct;
        }

        // Deletes a product by its ID
        public async Task<bool> DeleteProductAsync(int id)
        {
            var product = await _context.Products.FindAsync(id);
            if (product == null)
            {
                return false;
            }

            _context.Products.Remove(product);
            await _context.SaveChangesAsync();

            return true;
        }

        public async Task<ProcessingStatusDTO> StartProcessingAsync()
        {
            var operationId = Guid.NewGuid().ToString();
            var status = new ProcessingStatus
            {
                OperationId = operationId,
                Status = "Processing"
            };

            _context.ProcessingStatuses.Add(status);
            await _context.SaveChangesAsync();

            // Simulate asynchronous processing in a background task
            _ = Task.Run(async () =>
            {
                // Create Background Task
                await Task.Delay(TimeSpan.FromSeconds(10));
            });

            return new ProcessingStatusDTO
            {
                Id = status.Id,
                OperationId = operationId,
                Status = status.Status
            };
        }

        public async Task<ProcessingStatusDTO?> GetProcessingStatusAsync(int Id)
        {
            var status = await _context.ProcessingStatuses.FindAsync(Id);
            if (status == null)
            {
                return null;
            }

            return new ProcessingStatusDTO
            {
                Id = status.Id,
                OperationId = status.OperationId,
                Status = status.Status
            };
        }
    }
}

The ProductService encapsulates the business logic for managing products and processing operations. It provides asynchronous methods for CRUD (Create, Read, Update, Delete) product operations and handles the initiation and tracking of long-running processing tasks.

Register Services in Program Class

Configure necessary services for the dependency injection and middleware components for the Request Processing pipeline. So, please modify the Program class as follows. Registers ApplicationDbContext with the dependency injection container using the SQL Server connection string from appsettings.json.

using HTTPStatusCodeDemo.Data;
using HTTPStatusCodeDemo.Services;
using Microsoft.EntityFrameworkCore;

namespace HTTPStatusCodeDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.

            builder.Services.AddControllers()
                   .AddJsonOptions(options =>
                   {
                       // This will use the property names as defined in the C# model
                       options.JsonSerializerOptions.PropertyNamingPolicy = null;
                   });

            // Configure DbContext with SQL Server
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            // Register the ProductService as a singleton since we're using in-memory data
            builder.Services.AddScoped<ProductService>();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();

            app.UseAuthorization();

            app.MapControllers();

            app.Run();
        }
    }
}
Database Migration

Next, we need to generate the Migration and update the database schema. So, open the Package Manager Console and Execute the Add-Migration and Update-Database commands as follows.

2XX HTTP Status Codes in ASP.NET Core Web API Application with examples

With this, our Database with Employees and ClientSecrets tables should be created as shown in the below image:

2XX HTTP Status Codes in ASP.NET Core Web API Application with examples

Create the API Controller

Let’s create a simple Product Controller to demonstrate the use of these status codes. So, create an API Empty Controller named ProductsController within the Controllers folder and then copy and paste the following code:

using HTTPStatusCodeDemo.DTOs;
using HTTPStatusCodeDemo.Models;
using HTTPStatusCodeDemo.Services;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
namespace HTTPStatusCodeDemo.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class ProductsController : ControllerBase
{
private readonly ProductService _productService;
// Constructor injection of the service
public ProductsController(ProductService productService)
{
_productService = productService;
}
// Retrieves all products.
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<Product>))]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<ActionResult<IEnumerable<Product>>> GetAllProductsAsync()
{
try
{
var products = await _productService.GetAllProductsAsync();
if (products == null || !products.Any())
{
return NoContent();
}
return Ok(products);
}
catch (Exception ex)
{
//Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
// Retrieves a product by its ID.
[HttpGet("{id}", Name = "GetProductById")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponseDTO))]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<ActionResult<Product>> GetProductByIdAsync(int id)
{
try
{
var product = await _productService.GetProductByIdAsync(id);
if (product == null)
{
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status404NotFound,
message: $"Product with ID {id} not found."
);
return NotFound(errorResponse);
}
return Ok(product);
}
catch (Exception ex)
{
// Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
// Creates a new product.
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<ActionResult<Product>> CreateProductAsync([FromBody] ProductCreateDTO productDto)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var createdProduct = await _productService.CreateProductAsync(productDto);
return CreatedAtRoute("GetProductById", new { id = createdProduct.Id }, createdProduct);
}
catch (Exception ex)
{
// Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
// Updates an existing product.
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponseDTO))]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<ActionResult<Product>> UpdateProductAsync(int id, [FromBody] ProductUpdateDTO productDto)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if(id != productDto.Id)
{
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status400BadRequest,
message: $"Product ID Mixmatch"
);
return BadRequest(errorResponse);
}
var updatedProduct = await _productService.UpdateProductAsync(id, productDto);
if (updatedProduct == null)
{
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status404NotFound,
message: $"Product with ID {id} not found."
);
return NotFound(errorResponse);
}
return Ok(updatedProduct);
}
catch (Exception ex)
{
// Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
// Starts processing products asynchronously. 
[HttpPost]
[ProducesResponseType(StatusCodes.Status202Accepted, Type = typeof(ProcessingStatusDTO))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<ActionResult<ProcessingStatusDTO>> ProcessProductAsync()
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var processingStatusDTO = await _productService.StartProcessingAsync();
return AcceptedAtRoute("GetProcessStatusById", new { id = processingStatusDTO.Id }, processingStatusDTO);
//return AcceptedAtAction("GetProcessStatusAsync", "Products", new { id = processingStatusDTO.Id }, processingStatusDTO);
}
catch (Exception ex)
{
// Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
// Retrieves the status of a processing operation.
[HttpGet("{id}", Name = "GetProcessStatusById")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponseDTO))]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<ActionResult<ProcessingStatusDTO>> GetProcessStatusAsync(int id)
{
try
{
var status = await _productService.GetProcessingStatusAsync(id);
if (status == null)
{
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status404NotFound,
message: $"Processing operation with ID {id} not found."
);
return NotFound(errorResponse);
}
return Ok(status);
}
catch (Exception ex)
{
// Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
// Deletes a product by its ID.
[HttpDelete("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponseDTO))]
[ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ErrorResponseDTO))]
public async Task<IActionResult> DeleteProductAsync(int id)
{
try
{
var result = await _productService.DeleteProductAsync(id);
if (!result)
{
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status404NotFound,
message: $"Product with ID {id} not found."
);
return NotFound(errorResponse);
}
return NoContent();
}
catch (Exception ex)
{
// Log the Exception into a file or database
var errorResponse = new ErrorResponseDTO(
statusCode: StatusCodes.Status500InternalServerError,
message: "An error occurred while processing your request",
errorDetails: $"{ex.Message}" //Opionally you can Include the error details
);
return StatusCode(500, errorResponse);
}
}
}
}
Code Explanations:

The ProductsController serves as the API endpoint for managing products. This controller uses the ProductService to perform business operations and handles HTTP requests and responses. Each action method corresponds to specific HTTP verbs (GET, POST, PUT, DELETE) and returns appropriate 2XX HTTP Status Codes based on the outcome of the operations.

The Products Controller contains several action methods, each corresponding to specific CRUD operations and processing tasks. Let us understand how they use 2XX HTTP Status Codes to communicate successful outcomes to clients. Here, we are only focusing on 2XX HTTP Status Codes.

GetAllProductsAsync()

This method allows clients to fetch all available products. Depending on whether products exist, it appropriately returns 200 OK with data or 204 No Content if the product list is empty.

  • 200 OK: Returns this status code when the request successfully retrieves a list of products. The response includes the product data in the body.
  • 204 No Content: Returns this status code when the request is successful but there are no products to return. It indicates that the request was processed correctly, but there is no content to send in the response.

Method: GET

URL: https://localhost:7235/api/Products/GetAllProductsAsync

Expected Response: 200 OK with a list of products or 204 No Content.

GetAllProductsAsync()

GetProductByIdAsync(int id)

This method enables clients to retrieve a specific product by its id. If the product exists, it returns 200 OK with the product details, indicating a successful retrieval. While the method can also return 404 Not Found, outside the 2XX range, its primary 2XX response is 200 OK upon successful retrieval.

  • 200 OK: Returns this status code when a product with the specified ID is found. The response includes the product data.

Method: GET

URL: https://localhost:7235/api/Products/GetProductById/1

Expected Response: 200 OK with product details or 404 Not Found

GetProductByIdAsync(int id)

CreateProductAsync(ProductCreateDTO productDto)

This method allows clients to create a new product by sending the necessary data. Upon successful creation, it responds with 201 Created, signaling that the resource has been created and providing the URI of the new product. Although the method can return 400 Bad Requests for invalid input, its successful operation is indicated by 201 Created.

  • 201 Created: Returns this status code when a new product is successfully created. The response includes the created product data and a Location header pointing to the new resource.

Method: POST

URL: https://localhost:7235/api/Products/CreateProduct

Body:

{
"Name": "Tablet",
"Price": 299.99,
"Description": "Latest model tablet"
}

Expected Response: 201 Created with created product details or 400 Bad Request.

CreateProductAsync(ProductCreateDTO productDto)

UpdateProductAsync(int id, ProductUpdateDTO productDto)

This method enables clients to update the details of an existing product identified by ID. If the update operation succeeds, it responds with 200 OK, indicating that the changes have been applied successfully. The method can also return 404 Not Found if the product doesn’t exist, which is outside the 2XX range. The primary successful response is 200 OK.

  • 200 OK: Returns this status code when an existing product is successfully updated. The response includes the updated product data.

Method: PUT

URL: https://localhost:7235/api/Products/UpdateProduct/1

Body:

{
"Id": 1,
"Name": "Gaming Laptop",
"Price": 1299.99,
"Description": "High-end gaming laptop with RTX graphics"
}

Expected Response: 200 OK with updated product details or 404 Not Found.

UpdateProductAsync(int id, ProductUpdateDTO productDto)

ProcessProductAsync()

This method handles long-running or resource-intensive operations by initiating them asynchronously. Returning 202 Accepted informs the client that the request has been received and that processing will occur in the background, allowing the client to continue without waiting for the operation to complete.

  • 202 Accepted: Returns this status code when the request to start processing is accepted for asynchronous execution. The response includes a ProcessingStatusDTO containing an Id, OperationId, and the initial Status.

Method: POST

URL: https://localhost:7235/api/Products/ProcessProduct

Expected Response: 202 Accepted with ProcessingStatusDTO details or 400 Bad Request.

ProcessProductAsync()

GetProcessStatusAsync(int id)

This method allows clients to check the status of an asynchronous processing operation using the ID. If the operation exists, it responds with 200 OK, providing the current status (e.g., “Processing”, “Completed”). If the operation doesn’t exist, it returns 404 Not Found, outside the 2XX range. The successful response is 200 OK.

  • 200 OK: Returns this status code when the status of a processing operation is successfully retrieved. The response includes the current ProcessingStatusDTO.

Method: GET

URL: https://localhost:7235/api/Products/GetProcessStatusById/10

Expected Response: 200 OK with ProcessingStatusDTO details or 404 Not Found.

GetProcessStatusAsync(int id)

DeleteProductAsync(int id)

This method enables clients to delete a product by its id. Upon successful deletion, it responds with 204 No Content, signaling that the operation was successful and that there is no additional information to provide. If the product does not exist, it returns 404 Not Found, outside the 2XX range. The primary successful response is 204 No Content.

  • 204 No Content: Returns this status code when a product is successfully deleted. It indicates that the request was processed successfully, but the response body has no content to return.

Method: DELETE

URL: https://localhost:7235/api/Products/DeleteProduct/1

Expected Response: 204 No Content or 404 Not Found.

2XX HTTP Status Codes in ASP.NET Core Web API:

2XX HTTP Status Codes in ASP.NET Core Web API:
  • 200 OK: This status code indicates that the request has been successfully processed, and the response contains the requested resource, such as a list of products or a single product.
  • 201 Created: This status code indicates a new resource (product) has been created successfully.
  • 204 No Content: This status code is used when the request is successful, but there is no content to return, like when no products are available or after a successful deletion.
  • 202 Accepted: This status code indicates that a request has been accepted for processing but has not been completed yet. It’s useful for long-running tasks or asynchronous operations.

The 2XX category of HTTP Status codes indicates that the server successfully received, understood, and accepted the client’s request. It confirms that the action the client intended to perform was completed. That means these status codes are used to signify a successful interaction, whether it’s retrieving a resource (200 OK), creating a new resource (201 Created), or performing a long-running task in the background that does not complete immediately (202 Accepted) or performing a request that does not need to return data (204 No Content).

In the next article, I will discuss 3XX HTTP Status Codes in ASP.NET Core Web API applications with Examples. In this article, I explain 2XX HTTP Status Codes in ASP.NET Core Web API application with multiple Examples. I hope you enjoy this article on “2XX HTTP Status Codes in ASP.NET Core Web API”.

Leave a Reply

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