In a typical request-response cycle, the request and response headers contain a lot of additional information. This article talks about how to retrieve them and store them in a database. In this article, we’ll use PostgreSQL as the database and connect to it using dotConnect for PostgreSQL.

To be able to work with the code examples demonstrated in this article, you should have the following installed in your system:
    Visual Studio 2019 Community Edition
    PostgreSQL
    dotConnect for PostgreSQL

Create a new ASP.NET Core 5.0 Project in Visual Studio 2019

Assuming that the necessary software has been installed on your computer, follow the steps outlined below to create a new ASP.NET Core Web API project.

  • First off, open the Visual Studio 2019 IDE
  • Next, click "Create a new project" once the IDE has loaded
  • In the "Create a new project" screen, select “ASP.NET Core Web API” as the project template.
  • Click the "Next" button
  • Specify the project name and location - where it should be stored in your system
  • Optionally, click the "Place solution and project in the same directory" checkbox.
  • Next, click the "Create" button
  • In the "Create a new ASP.NET Core Web Application" dialog window that is shown next, select "API" as the project template.
  • In the “Additional Information” screen, .NET 5.0 is the framework version.
  • You should disable the "Configure for HTTPS" and "Enable Docker Support" options by disabling the respective checkboxes.
  • Since we'll not be using authentication in this example, specify authentication as "No Authentication".
  • Finally, click on the "Create" button to finish the process.

This will create a new ASP.NET Core Web API project in Visual Studio.

Install NuGet Package(s)
To work with dotConnect for PostgreSQL in ASP.NET Core 5, you should install the following package into your project:
Devart.Data.PostgreSQL

You have two options for installing this package: either via the NuGet Package Manager or through the Package Manager Console Window by running the following command.
PM> Install-Package Devart.Data.PostgreSQL

Request and Response Headers in ASP.NET Core
Request headers provide more information about the requested resource or the client who is requesting it. You can take advantage of request headers to add extra information to the HTTP Request.

The response headers contain additional information about the response, such as its location and the server. It is an HTTP header that can only be used in an HTTP response and doesn't have to do anything with the content of the message. To provide more context to the response, you can use response headers like Age, Server, and Location.

Both Request headers and Response headers are represented as a collection of key-value pairs that can be passed back and forward between the client and the server.

Reading Request and Response Headers in ASP.NET Core
You can read request and response headers using the Request and Response properties of the HttpContext class. These properties are of HttpRequest and HttpResponse types respectively.

You can use the following code to retrieve the request headers in ASP.NET:
List < string > AllRequestHeaders = new List < string > ();
var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);


The following code snippet can be used to retrieve all response headers:
List < string > AllResponseHeaders = new List < string > ();
var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);


Building a Middleware to Read Request and Response Headers

A middleware is a software component that processes requests and responds. ASP.Net Core typically has a series of middleware components - these middleware components either process requests or pass them to the next component in the request processing pipeline.

Create a new class in your project's root and name it as RequestResponseHeaderMiddleware. Next, replace the default code with the following:
public class RequestResponseHeadersMiddleware {
    private readonly RequestDelegate _next;
    public RequestResponseHeadersMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext) {
        await _next.Invoke(httpContext);
    }
}

This is a minimalistic implementation of middleware in ASP.NET Core. However, it doesn’t do anything other than passing the control to the next component in the pipeline.

We need to add the logic of reading requests and response headers. We’ve already written the code in the previous section. Here’s the updated version of our middleware:
public class RequestResponseHeadersMiddleware {
    private readonly RequestDelegate _next;
    public readonly List < string > AllRequestHeaders = new List < string > ();
    public readonly List < string > AllResponseHeaders = new List < string > ();
    public RequestResponseHeadersMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext) {
        var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllRequestHeaders.AddRange(requestHeaders);
        await this._next.Invoke(httpContext);
        var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllResponseHeaders.AddRange(uniqueResponseHeaders);
        await _next.Invoke(httpContext);
    }
}


Create an Extension Method for the Middleware
We’ll now create an extension method for our middleware to be able to conveniently configure the middleware in the Configure method of the Startup class.

To do this, create a new class named RequestResponseHeadersMiddlewareExtensions in a file called RequestResponseHeadersMiddlewareExtensions.cs with the following code in there:
public static class RequestResponseHeadersMiddlewareExtensions {
    public static IApplicationBuilder UseRequestResponseHeadersMiddleware(this IApplicationBuilder builder) {
        return builder.UseMiddleware < RequestResponseHeadersMiddleware > ();
    }
}


Configure the Middleware in the Startup Class
You can write the following code in the Configure method of the Startup class to enable the custom middleware we have built thus far.
app.UseRequestResponseHeadersMiddleware();

Create the Model
Now create the following class in a file of the same name having an extension .cs. We'll use it to store request and response header values.
public class RequestResponseHeader {
    public string RequestHeader {
        get;
        set;
    }
    public string ResponseHeader {
        get;
        set;
    }
}


Create the DbManager Class
The DbManager class wraps all calls made to the database using dotConnect for Postgresql. It has just one method named Save to persist the request and response header values in the Postgresql database.
public class DbManager {
    private readonly string connectionString = "Some connection string...";
    public int Save(RequestResponseHeader requestResponseHeader) {
        try {
            using(PgSqlConnection pgSqlConnection = new PgSqlConnection(connectionString)) {
                using(PgSqlCommand cmd = new PgSqlCommand()) {
                    cmd.CommandText = "INSERT INTO
                    public.requestresponseheaders " +
                    "(requestheader, responseheader) " + "VALUES (@requestheader, @responseheader)";
                    cmd.Connection = pgSqlConnection;
                    cmd.Parameters.AddWithValue("requestkey", requestResponseHeader.RequestHeader);
                    cmd.Parameters.AddWithValue("responsevalue", requestResponseHeader.ResponseHeader);
                    if (pgSqlConnection.State != System.Data.ConnectionState.Open) pgSqlConnection.Open();
                    return cmd.ExecuteNonQuery();
                }
            }
        } catch {
            throw;
        }
    }
}


Call the Save Method from the Middleware
We’ll now modify the middleware we’ve implemented to store the request and response headers in a PostgreSQL database using dotConnect for PostgreSQL.

You can use the following code snippet to call the Save method of the DbManager class from the middleware we implemented earlier.
for (int index = 0; index < AllRequestHeaders.Count; index++) {
    RequestResponseHeader requestResponseHeader = new
    RequestResponseHeader();
    requestResponseHeader.RequestHeader = AllRequestHeaders[index];
    requestResponseHeader.ResponseHeader = AllResponseHeaders[index];
    dbManager.Save(requestResponseHeader);
}

As you can see here, there are two string collections namely AllRequestHeaders and AllResponseHeaders that hold the request and response header values respectively. We saw how it is done earlier in the article.

In this code snippet, an instance of RequestResponseHeader is created, its properties initialized and then this instance is passed as a parameter to the Save method.

Here is the complete code of the middleware for your reference:
public class RequestResponseHeadersMiddleware {
    private readonly RequestDelegate _next;
    public readonly List < string > AllRequestHeaders = new List < string > ();
    public readonly List < string > AllResponseHeaders = new List < string > ();
    private readonly DbManager dbManager = new DbManager();
    public RequestResponseHeadersMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext) {
        var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllRequestHeaders.AddRange(requestHeaders);
        await this._next.Invoke(httpContext);
        var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllResponseHeaders.AddRange(uniqueResponseHeaders);
        await _next.Invoke(httpContext);
        for (int index = 0; index < AllRequestHeaders.Count; index++) {
            RequestResponseHeader requestResponseHeader = new
            RequestResponseHeader();
            requestResponseHeader.RequestHeader = AllRequestHeaders[index];
            requestResponseHeader.ResponseHeader = AllResponseHeaders[index];
            dbManager.Save(requestResponseHeader);
        }
    }
}


In ASP.NET Core, you can read request and response headers in your application easily. Request headers allow you to work with optional data that is stored as key-value pairs. Response headers include extra information about the response that allows for a more comprehensive context of the response to be sent to the client.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.