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

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

In this article, I will explain 1XX HTTP Status Codes in ASP.NET Core Web API Application with examples. While the 2XX, 3XX, 4XX, and 5XX status codes are widely recognized and frequently utilized, the 1XX status codes often remain underappreciated. 1XX codes are less commonly used directly by application developers. Here, I will show how you might implement or observe these codes in real-world ASP.NET Core applications.

What are 1XX HTTP Status Codes?

1XX HTTP status codes (i.e., those that start with 1) are informational response codes. These codes indicate that the initial part of a request has been received and understood by the server, and the client can continue with the request body (in case of a POST request) or proceed to receive a final response. These codes typically do not contain a response body but sometimes include headers that provide more information about the current status or the next steps the client should take.

They are generally used in scenarios where the client and server need to communicate about the ongoing state of a request before sending the final response. These status codes are typically not visible to end-users, as they are mainly used for communication between the client and server during the processing of a request. Unlike other status codes (2XX, 3XX, 4XX, and 5XX), 1XX codes are rarely used in everyday web applications but can be crucial in specific scenarios requiring advanced communication scenarios. Common 1XX Status Codes:

  • 100 Continue
  • 102 Processing
  • 103 Early Hints
Creating New ASP.NET Core Web API Project:

First, create a new ASP.NET Core Web API Project named HTTPStatusCodeDemo. Once you created the project, please modify the Program class as follows:

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

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

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

100 Continue HTTP Status Code

The 100 Continue status code is sent by the server to inform the client that the initial part of the request (request headers) has been received. and not yet rejected by the server, and the client should proceed to send the rest of the request body. It’s commonly used in scenarios where a client sends a large payload. By first sending a small part of the request (such as headers), the client waits for a 100 Continue response from the server before sending the rest of the payload.

This status code is primarily used to handle large data uploads in web services. The client begins by sending an Expect: 100-continue header and waits for the server to send a 100 Continue response before sending the data. If the server responds with an error (like 403 Forbidden), the client stops and saves bandwidth. This approach avoids unnecessary data transfer if the server decides to reject the request early.

Use Cases for 100 Continue:
  • File Uploads or Large Payloads: When a client uploads a large file to the server, it might send only the headers first. The server then checks if the headers (authentication, content type, etc.) are valid and responds with 100 Continue. After receiving this response, the client proceeds with uploading the full file.
  • API Request Validation: The client sends initial headers to validate the request format or authentication before sending the full payload.
  • Conditional Requests: In situations where a client is sending a large request body, and the server has to validate it first (for example, checking if the file already exists or validating certain conditions), the server can reply with a 100 Continue before the client sends the rest of the data.
How to Return 100 Continue in ASP.NET Core Web API?

In most cases, ASP.NET Core handles 100 Continue automatically if the client sends an Expect: 100-continue header. You generally do not manually return 100 Continue in your controller logic. Instead, the Kestrel server will process the Expect header and respond automatically if needed. However, if you want to demonstrate or force a 100 Continue response, you can manipulate the response stream at a lower level (though this is very uncommon).

LargeFileController:

Let us demonstrate manually sending 100 Continue for large file uploads. So, create an API Empty Controller named LargeFileController within the Controllers folder and then copy and paste the following code. We will create an endpoint that accepts large file uploads to demonstrate the 100 Continue behavior. The UploadFile Method Accepts a file via POST and saves it to the server, demonstrating how 100 Continue allows the client to send large files efficiently.

using Microsoft.AspNetCore.Mvc;

namespace HTTPStatusCodeDemo.Controllers
{
    // Demonstrates manual usage of 100 Continue for a large file upload scenario.
    [ApiController]
    [Route("api/[controller]")]
    public class LargeFileController : ControllerBase
    {
        private readonly string _targetFilePath = Path.Combine(Directory.GetCurrentDirectory(), "Uploads");

        // Simulates an endpoint that accepts a large file upload and manually sends 100 Continue.
        // returns: A success message upon file upload completion.
        [HttpPost("upload-large-file")]
        [RequestSizeLimit(524288000)] // 500 MB limit
        public async Task<IActionResult> UploadLargeFile(IFormFile file)
        {
            try
            {
                // Check if the client used Expect: 100-continue
                if (Request.Headers.ContainsKey("Expect")
                    && Request.Headers["Expect"].ToString().Equals("100-continue", StringComparison.OrdinalIgnoreCase))
                {
                    // Manually send 100 Continue
                    HttpContext.Response.StatusCode = 100;

                    // Flush the response so the client actually receives the 100 Continue
                    await HttpContext.Response.Body.FlushAsync();
                }

                // Ensure the upload directory exists
                if (!Directory.Exists(_targetFilePath))
                {
                    Directory.CreateDirectory(_targetFilePath);
                }

                var filePath = Path.Combine(_targetFilePath, file.FileName);

                // Save the file to the server
                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }

                // Return final response (200 OK) indicating successful upload
                return Ok(new { message = "File uploaded successfully.", fileName = file.FileName });
            }
            catch (Exception ex)
            {
                // Log exception details here
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }
    }
}

In the above example, we are sending a 100 Continue status code manually (though ASP.NET Core typically does this automatically). This scenario simulates a large file upload where the server responds with 100 Continue before receiving the entire payload.

102 Processing HTTP Status Code

The 102 Processing status code indicates to the client that the server has received and is processing the request, but no final response is available yet. This is primarily used with WebDAV (Web-based Distributed Authoring and Versioning) requests to prevent the client from timing out. This is helpful for long-running operations, allowing the client to avoid timeouts and continue waiting for the final response.

Use Cases for 102 Processing:
  • Long-Running Requests: For example, if a user uploads a large document that is being processed in the background, the server might respond with a 102 Status Code to prevent the client from timing out while waiting for the response. Informing the client that the request is being processed (e.g., background job execution or large database operations).
  • Asynchronous Task Status: In scenarios where the client requests a complex operation (such as indexing a large dataset), the server might send 102 Processing until it completes the operation and sends a final status code (like 200 OK or 201 Created).
How to Return 102 HTTP Status Code in ASP.NET Core Web API?

While 102 Processing is typically associated with WebDAV, you can send it manually by setting the status code in your controller action or middleware. For example, Response.StatusCode = 102; can be used before continuing with a long-running task.

LongRunningController:

Let us demonstrate manually sending 102 Processing for a simulated long-running task. So, create an API Empty Controller named LongRunningController within the Controllers folder and then copy and paste the following code:

using Microsoft.AspNetCore.Mvc;

namespace _3XXHTTPStatusCodeDemo.Controllers
{
    // Demonstrates manual usage of 102 Processing for long-running tasks.
    [ApiController]
    [Route("api/[controller]")]
    public class LongRunningController : ControllerBase
    {
        // Simulates a long-running task, sending 102 Processing to let the client know we are still working.
        // returns: A success message when processing completes.
        [HttpGet("long-task")]
        public async Task<IActionResult> LongTask()
        {
            try
            {
                // 1. Send 102 Processing (informational)
                HttpContext.Response.StatusCode = 102;

                // 2. Flush so the client receives the 102 Processing immediately
                await HttpContext.Response.Body.FlushAsync();

                // 3. Simulate a long-running operation (5 seconds here)
                await Task.Delay(5000);

                // 4. Return a final 200 OK response
                return Ok("Long-running task completed!");
            }
            catch (Exception ex)
            {
                // Log exception details here
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }
    }
}

In the above example, we are sending a 102 Processing status code to inform the client that the server is still working on the request. Useful in scenarios where you want to prevent timeouts for long-running operations.

103 Early Hints HTTP Status Code

The 103 Early Hints status code is used to return preliminary response headers (such as Link headers) to a client before the final response. This is useful for optimizing page load times by allowing clients to start preloading resources like CSS, JavaScript, images, or other assets, improving performance, especially on slow networks. By sending hints to preload certain resources, the client can begin fetching them while the server is still finalizing its main response.

Use Cases for 103 Early Hints:
  • Resource Preloading: Sending early hints to the client to preload critical resources while the server is preparing the full response. This can significantly improve page load times by downloading essential assets early.
How to Return 103 Early Hints in ASP.NET Core Web API?

103 Early Hints is an HTTP/2+ concept and not all clients or browsers fully support it. ASP.NET Core does not have a high-level built-in method to send 103 Early Hints, so you typically have to write to the response stream directly.

EarlyHintsController:

Let us demonstrate manually sending 103 Early Hints to optimize resource loading. So, create an API Empty Controller named EarlyHintsController within the Controllers folder and then copy and paste the following code:

using Microsoft.AspNetCore.Mvc;
namespace HTTPStatusCodeDemo.Controllers
{
    // Demonstrates manual usage of 103 Early Hints to preload resources.
    [ApiController]
    [Route("api/[controller]")]
    public class EarlyHintsController : ControllerBase
    {
        // Simulates sending 103 Early Hints (e.g., to preload a CSS file) before final response.
        // returns: A success message after sending early hints.
        [HttpGet("preload-resources")]
        public async Task<IActionResult> PreloadResources()
        {
            try
            {
                // Set status code to 103
                HttpContext.Response.StatusCode = 103;

                // Example: Provide a Link header to preload a CSS file (or any critical resource)
                // HttpContext.Response.Headers.Append("Link", "</static/styles.css>; rel=preload; as=style");

                HttpContext.Response.Headers.Append("Link", "</styles.css>; rel=preload");
                HttpContext.Response.Headers.Append("Link", "</script.js>; rel=preload");

                // 3. Flush the response so the client receives the 103 Early Hints
                await HttpContext.Response.Body.FlushAsync();

                // 4. Simulate server preparing a final response
                await Task.Delay(2000);

                return Ok("Final response after Early Hints!");
            }
            catch (Exception ex)
            {
                // Log exception details here
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }
    }
}

In the above example, we are sending a 103 Early Hints status code so the client can preload resources before the final response. This can improve page performance when the client supports early hints.

Summary:

1XX HTTP Status Codes provide valuable mechanisms for handling communication between the client and server during the request processing phase. Although not frequently visible to end-users, these status codes are crucial in optimizing client-server interactions, particularly for handling large requests, protocol upgrades, and long-running operations. In most ASP.NET Core Web API projects, developers rarely implement 1XX codes manually because the framework (or the underlying web server) handles them automatically (especially 100 and 101).

By understanding 100 Continue, 101 Switching Protocols, and 102 Processing developers can build more efficient, responsive, and user-friendly APIs.

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

Leave a Reply

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