Reading Request Headers Across Multiple .NET Core API Controllers

I was working on creating a .NET Core-based API and came across a requirement to read a particular request header across the API controllers.  To understand it better, let us say there are two API controllers,

  1. InvoiceController
  2. ProductController

We need to read the value of a particular Request Header in both controllers.

To do that, add a middleware class; I am naming it RequestCodeMiddleware, as we will read a request header named-  “Request-Code.”


public class RequestCodeMiddleware
{
    private readonly RequestDelegate _next;

    public RequestCodeMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // Read the request code here. This is just an example, replace it with your actual logic.
        var requestCode = context.Request.Headers["Request-Code"].FirstOrDefault();
        // Add the request code to the HttpContext
        context.Items["RequestCode"] = requestCode+"middle ware";
        
        // what is stopping us to read client id 
        // will that be a good practice ?
        // Call the next middleware in the pipeline
        await _next(context);
    }
}

After creating the middleware class, register it to the API handling pipeline by adding the below code,


if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseMiddleware<RequestCodeMiddleware>();
app.UseHttpsRedirection();
app.MapControllers();
app.Run();


Now, you can read the request header in a ProductController’s GET Action, as shown below.


public class product : ControllerBase
{
    
    [HttpGet]
    public string Get()
    {
        var requestCode = HttpContext.Items["RequestCode"] as string;
        return requestCode;
    }
}


So far, so good; however, there is still a challenge: the above code must be duplicated to read the request header in the multiple Actions. To avoid that, we can read it inside the controller’s constructor; however, HttpContext is unavailable inside a controller’s constructor.

Another approach is to use IHttpContextAccesor.

To use IHttpContextAccesor, register it in the API startup pipeline as shown below,


builder.Services.AddHttpContextAccessor();

Now in the constructor of the InvoiceController, you can inject IHttpContextAccesor to read the request header as shown in the below code listing.


public class invoice : ControllerBase
    {

        private readonly IHttpContextAccessor _httpContextAccessor;
        private string _requestCode;

        public invoice(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
            _requestCode = _httpContextAccessor.HttpContext.Items["RequestCode"] as string;
        }

     // Your action methods..
     // GET: api/<invoice>
        [HttpGet]
        public string Get()
        {
            return _requestCode;
        }
      }


In this way, we can read a request header in multiple controllers.  I hope you find this post helpful. Thanks for reading.


Discover more from Dhananjay Kumar

Subscribe to get the latest posts sent to your email.

Published by Dhananjay Kumar

Dhananjay Kumar is founder of NomadCoder and ng-India

Leave a comment

Discover more from Dhananjay Kumar

Subscribe now to keep reading and get access to the full archive.

Continue reading