C# – How to add request headers when using HttpClient

There are two ways add request headers when using HttpClient:

  • Add headers for all requests using HttpClient.DefaultRequestHeaders.
  • Add headers per request using HttpRequestMessage.Headers.

In this article, I’ll show examples of both ways to add request headers.

Add an unchanging header for all requests

Let’s say you’re adding an API Key header. It needs to be included in all requests and the value won’t change.

To add this request header, you can use HttpClient.DefaultRequestHeaders when you’re initializing the HttpClient instance, like this:

public class RandomNumberService { private readonly HttpClient HttpClient; private const string key = "123"; public RandomNumberService() { HttpClient = new HttpClient(); HttpClient.DefaultRequestHeaders.Add("ApiKey", key); } public async Task<string> GetRandomNumber() { var response = await HttpClient.GetAsync(GetRandomNumberUrl); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } }
Code language: C# (cs)

Here’s what the request looks like in Fiddler:

GET https://localhost:12345/RandomNumber HTTP/1.1 Host: localhost:12345 ApiKey: 123
Code language: plaintext (plaintext)

It includes the ApiKey header in all requests. This only had to be configured once.

Add a header per request

To add a header per request, use HttpRequestMessage.Headers + HttpClient.SendAsync(), like this:

public class RandomNumberService { private readonly HttpClient HttpClient; private const string randomNumberUrl = "https://localhost:12345/RandomNumber"; public RandomNumberService() { HttpClient = new HttpClient(); } public async Task<string> GetRandomNumber(string Token) { using (var request = new HttpRequestMessage(HttpMethod.Get, randomNumberUrl)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", Token); var response = await HttpClient.SendAsync(request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } } }
Code language: C# (cs)

First, it’s best practice to use a single HttpClient instance for multiple requests. Since you’re using a single instance, don’t use HttpClient.DefaultRequestHeaders for headers that need to be applied per request. It’s not thread-safe. This is why you have to use HttpRequestMessage.Headers instead.

Second, you have to use HttpClient.SendAsync() to send the request because there are no overloads of GetAsync() / PostAsync() that take an HttpRequestMessage parameter.

Here’s an example of what multiple requests look like in Fiddler:

GET https://localhost:12345/RandomNumber HTTP/1.1 Host: localhost:12345 Authorization: Bearer 11 GET https://localhost:12345/RandomNumber HTTP/1.1 Host: localhost:12345 Authorization: Bearer 12
Code language: plaintext (plaintext)

Notice a unique authorization header was added to each request.

GetWithHeadersAsync() extension method for per request headers

HttpClient.GetAsync() / PostAsync() are convenience methods. It would be nice if there were overloads of these that accepted a list of per request headers, but there aren’t.

If you don’t want to have HttpRequestMessage + SendAsync() all over the place, you can abstract that logic away by using extension methods. Here’s an example:

public static class HttpClientExtensions { public static async Task<HttpResponseMessage> GetWithHeadersAsync(this HttpClient httpClient, string requestUri, Dictionary<string, string> headers) { using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri)) { foreach(var header in headers) { request.Headers.Add(header.Key, header.Value); } return await httpClient.SendAsync(request); } } }
Code language: C# (cs)

You can use the extension method in a similar way that you’re used to using GetAsync():

public async Task<string> GetRandomNumber(string Token) { var response = await HttpClient.GetWithHeadersAsync(randomNumberUrl, new Dictionary<string, string>() { ["Authorization"] = $"Bearer {Token}" }); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); }
Code language: C# (cs)

This is just one extension method. You can use this as starting point. I wouldn’t bother adding extension methods for all possible overloads of GetAsync() or PostAsync().

Use HttpRequestHeaders properties for adding common headers

You can add any header using .Add(key, value). For common headers, such as Authorization, you can also add the header through properties in HttpRequestHeaders. This can help you avoid mistakes and improves readability.

For example, you can add the Authorization header in these two functionally equivalent ways:

//Option 1 request.Headers.Add("Authorization", $"Bearer {Token}"); //Option 2 - Using the common header property request.Headers.Authorization = new AuthenticationHeaderValue(scheme: "Bearer", parameter: Token);
Code language: C# (cs)

4 thoughts on “C# – How to add request headers when using HttpClient”

  1. Good examples but what are the allowed values for the scheme parameter for AuthenticationHeaderValue ?

    Is this just the “username” and set by whoever coded up the API?

    Reply
    • There are a few standard HTTP auth schemes , such as Basic and Bearer, but AuthenticationHeaderValue doesn’t validate what you pass in. It just formats it properly for you. You’ll want to set the auth headers according to what the web API you’re integrating with requires.

      Reply
  2. I am using DefaultRequestHeaders.Add to add ClientId and ClientSecret to hit one of the mulesoft endpoints but I was asked to add a GUID in every request header to successfully hit the endpoint. I am generating the GUID in code but in order to add it to headers along with existing ClientId and ClientSecret, how can I do that?

    Reply
    • Hi Sunny,

      Keep using HttpClient.DefaultRequestHeaders.Add for the two headers that are the same for all requests – ClientId and ClientSecret.

      For the other header, where you are generating a unique value for each request, you’ll have to build an HttpRequestMessage, use HttpRequestMessage.Headers.Add(), and send it with HttpClient.SendAsync(). Check the “Add a header per request” section in the article for a code example.

      Reply

Leave a Reply to david gray Cancel reply