In this article, we are going to learn about the different ways we can extract Custom Headers from our ASP.NET Core Web API requests.
Let’s start.
VIDEO: How to Work With Custom Headers in .NET Core Applications.
What Are HTTP Headers?
HTTP headers are part of every HTTP request in both the request and response data.
It contains metadata information such as security authentication information, the agent used, and cache control. In our requests, we can already find some predefined HTTP headers, however, we can use custom HTTP headers if needed.
To see what headers look like, we can inspect a full HTTP header request from Postman:
GET /api2/headers/from-middleware HTTP/1.1 CustomHeaderKey: CustomHeaderValue User-Agent: PostmanRuntime/7.29.2 Accept: */* Postman-Token: 78eb9192-ce96-421c-879c-1a4eae8e2303 Host: localhost:7202 Accept-Encoding: gzip, deflate, br Connection: keep-alive
The first line is the request and the rest are HTTP headers. That is to say, the method, route, and protocol are the elements that make up the request.
And in this request, we can see a CustomHeaderKey
custom header with its value.
Now we can start to explore options to extract the headers and use them in controllers, filters, or middlewares.
Basic HTTP Header Extraction
Manipulating with HTTP headers in ASP.NET Core is easy enough to do as part of an execution that has access to the Request.Headers
dictionary.
In ASP.NET Core, the IHeaderDictionary
is the interface that defines the HTTP request headers. These headers comprise a key-value pairs dictionary. The header keys are strings and the header values are StringValues
structs:
[HttpGet("from-basic")] public IActionResult ExtractFromBasic() { const string HeaderKeyName = "HeaderKey"; Request.Headers.TryGetValue(HeaderKeyName, out StringValues headerValue); return Ok(headerValue); }
In this action, we declare a HeaderKeyName
constant with the custom header name, and we access the Headers
dictionary through the HTTP Request object. Then, we extract a header, with the name of HeaderKey
, invoke the TryGetValue
method and set the value to the headerValue
variable.
Testing Basic HTTP Header Extraction
We are going to test our endpoint by using Postman:
We can see, we have a GET request to our endpoint, and we also set a custom HeaderKey
header with its HeaderValue
value.
Attribute HTTP Header Extraction
ASP.NET Core introduces the FromHeader
attributes:
[HttpGet("from-header-attribute")] public IActionResult ExtractFromQueryAttribute([FromHeader] HeaderDTO headerDTO) { return Ok(headerDTO); }
We use the FromHeader
attribute to specify that a parameter or property should be bound using the request headers.
Of course, for this to work, we need the HeaderDTO
class:
public class HeaderDTO { [FromHeader] public string FirstName { get; set; } = string.Empty; [FromHeader] public string LastName { get; set; } = string.Empty; }
By using the FromHeader
attribute, we will bind every property of the HeaderDTO
object to the HTTP request headers.
Testing Attribute HTTP Header Extraction
Again, let’s use Postman to send a GET request with the FirstName
and LastName
custom headers to our new endpoint: https://localhost:7202/api/headers/from-header-attribute
.
In the response, we can find the custom headers: FirstName
and LastName
.
Custom Header Extraction Using Action Filter
If we want to ensure the extraction of any custom header in any endpoint in our ASP.NET Core Web API, we can use ASP.NET Core action filters.
An action filter is another possibility that we have to extract a custom header value before an action is invoked:
public class ExtractCustomHeaderAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { const string HeaderKeyName = "FilterHeaderKey"; context.HttpContext.Request.Headers.TryGetValue(HeaderKeyName, out StringValues headerValue); if (context.HttpContext.Items.ContainsKey(HeaderKeyName)) { context.HttpContext.Items[HeaderKeyName] = headerValue; } else { context.HttpContext.Items.Add(HeaderKeyName, $"{headerValue}-received"); } } }
The ExtractCustomHeaderAttribute
class inherits from ActionFilterAttribute
, which allows us to use it as an attribute [ExtractCustomHeader]
. It also allows us the override the OnActionExecuting
method, which is called before the action method is invoked. In this method, we use the context.HttpContext.Items
dictionary to store the custom header value.
Once we have the header key/value pair in the dictionary, we can extract it in our action:
[HttpGet("from-filter")] [ExtractCustomHeader] public IActionResult ExtractFromFilter() { const string HeaderKeyName = "FilterHeaderKey"; HttpContext.Items.TryGetValue(HeaderKeyName, out object? filterHeaderValue); return Ok(filterHeaderValue); }
We use theExtractCustomHeader
attribute to execute the action filter, that sets the header key/value to the Items
dictionary. We can use this attribute at multiple endpoints, and also at the Controller level. Inside the action, we just extract the header value and return it as a result.
Custom Header Extraction Using Middleware
We can also use ASP.NET Core middleware to extract headers in ASP.NET Core.
Let’s create a super-simple middleware to extract the custom header value in the Program.cs
class:
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api2"), appBuilder => { appBuilder.UseMiddleware<ExtractCustomHeaderMiddleware>(); });
The UseWhen
allows us to “branch” the pipeline. We can use it to conditionally invoke middleware based on the request path. In other words, if the request path starts with the given path, we will execute our middleware.
And after registering our middleware we can implement:
public class ExtractCustomHeaderMiddleware { private readonly RequestDelegate _next; public ExtractCustomHeaderMiddleware(RequestDelegate next) => _next = next; public async Task InvokeAsync(HttpContext context) { const string HeaderKeyName = "MiddlewareHeaderKey"; context.Request.Headers.TryGetValue(HeaderKeyName, out StringValues headerValue); if (context.Items.ContainsKey(HeaderKeyName)) { context.Items[HeaderKeyName] = headerValue; } else { context.Items.Add(HeaderKeyName, $"{headerValue}-received"); } await _next(context); } }
Here, we implement the InvokeAsync
method, which gives us access to the current HttpContext
. Furthermore, we can use this HttpContext
to add our custom header value and the next Task
to execute in the pipeline.
Conclusion
In this article, we’ve learned how to extract a custom header to our ASP.NET Core Web API request using four different strategies.