189

I'm implementing an API made by other colleagues with Apiary.io, in a Windows Store app project.

They show this example of a method I have to implement:

var baseAddress = new Uri("https://private-a8014-xxxxxx.apiary-mock.com/");

using (var httpClient = new HttpClient{ BaseAddress = baseAddress })
{
    using (var response = await httpClient.GetAsync("user/list{?organizationId}"))
    {
        string responseData = await response.Content.ReadAsStringAsync();
    }
}

In this and some other methods, I need to have a header with a token that I get before.

Here's an image of Postman (chrome extension) with the header I'm talking about: enter image description here

How do I add that Authorization header to the request?

Massimiliano Kraus
  • 3,214
  • 5
  • 20
  • 40
Ric
  • 4,139
  • 4
  • 25
  • 59
  • 3
    possible duplicate of [Setting Authorization Header of HttpClient](http://stackoverflow.com/questions/14627399/setting-authorization-header-of-httpclient) – Daniel Kelley Apr 22 '15 at 14:52
  • 8
    *Warning* For potential code searchers: this is an incorrect use of HttpClient!! Check https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ why. – 321X Jul 06 '18 at 09:50

6 Answers6

362

A later answer, but because no one gave this solution...

If you do not want to set the header on the HttpClient instance by adding it to the DefaultRequestHeaders, you could set headers per request.

But you will be obliged to use the SendAsync() method.

This is the right solution if you want to reuse the HttpClient -- which is a good practice for

Use it like this:

using (var requestMessage =
            new HttpRequestMessage(HttpMethod.Get, "https://your.site.com"))
{
    requestMessage.Headers.Authorization =
        new AuthenticationHeaderValue("Bearer", your_token);
    
    await httpClient.SendAsync(requestMessage);
}
JTech
  • 3,076
  • 5
  • 37
  • 46
Philippe
  • 21,230
  • 5
  • 41
  • 62
  • 10
    Seems safer to not use DefaultRequestHeaders if the value changes frequently. – Jason Rowe Dec 14 '16 at 16:52
  • 3
    Note you very likely need `requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", your_token);` "Bearer" would be an invalid HTTP header – Chris Marisic Jan 06 '17 at 03:41
  • 4
    Thanks for this, we're reusing our HttpClient and this helped us – StevenMcD May 08 '17 at 04:28
  • 1
    Everyone nowadays reuses the very same instance (as per the official recommendation), this one is the actual answer then. – Wiktor Zychla Mar 15 '18 at 13:09
  • -1 for not using `using`. ALL non managed resources MUST be disposed. It's not just about best practice, it's about not blowing up a server. Other than that, that should be the accepted answer (see my comment on the accepted answer) – JCKödel Jun 03 '18 at 21:23
  • 2
    @JCKodel it would have added noise because you're not necessary obliged to use `using` but could instantiate in the constructor and dispose in the `Dispose()` – Philippe Jun 03 '18 at 22:22
  • @JCKödel A link on how using HttpClient well (without `using`!) https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ – Philippe Jun 07 '18 at 08:04
  • 4
    I never said use `using` on HttpClient (this is bad), I said on HttpRequesMessage (because it have unmanaged memory buffers for streaming that MUST be disposed after the use). The request and response are and must be disposed every request (otherwise you'll keep large memory chunks locked for a long time). The `HttpClient` is reusable, to an extend. – JCKödel Jun 08 '18 at 18:34
  • @JCKödel why is it bad to be `using` the `HttpClient`? – Bondolin May 21 '19 at 13:18
  • @JCKödel if you mean not `using` a `new HttpClient` for each request, I agree completely. But is there a problem with `using` a client for multiple requests? – Bondolin May 21 '19 at 14:22
  • @Bondolin I think you misunderstood `using` was meaning using the keyword `using(){}` which dispose the instance.... – Philippe May 21 '19 at 14:42
  • No, that's precisely what I meant. My understanding is that there is nothing wrong with `using` an `HttpClient`, doing a few requests, and then disposing of the client at the end of the `using` block. I do not like the approach of a static client that never gets disposed. – Bondolin May 21 '19 at 15:03
  • 1
    The best is to have 1 httpClient for each api/server to query and keep it as long as possible. Which is most of the time incompatible with using `using`. Static could be good (at least better that multiple instances) but better is to use dependency injection. One instance kept all along the application lifetime is good. – Philippe May 21 '19 at 20:59
  • This thread is another tribute to IDisposable as a failure of the language designers. You must not dispose HttpClient, but you must always dispose HttpRequestMessage. It's a recipe for disaster as developers must learn this one blown up server at a time. – Skrymsli Jan 20 '21 at 22:48
214

When using GetAsync with the HttpClient you can add the authorization headers like so:

httpClient.DefaultRequestHeaders.Authorization 
                         = new AuthenticationHeaderValue("Bearer", "Your Oauth token");

This does add the authorization header for the lifetime of the HttpClient so is useful if you are hitting one site where the authorization header doesn't change.

Here is an detailed SO answer

ΩmegaMan
  • 22,885
  • 8
  • 76
  • 94
kmcnamee
  • 4,425
  • 2
  • 21
  • 34
  • 61
    -1 because HttpClient must be reusable (see https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/). If it must be reusable, setting the default request headers is a bad practice. – JCKödel Jun 03 '18 at 21:22
  • 36
    @JCKödel That's a false assumption you are making. If you are always calling the same site with the same credentials for the lifetime of the HttpClient using the DefaultRequestHeaders saves you from having to continuously set them again with the same values. You should re-read that article it talks about using the same instance of the HttpClient, it makes no statements about default request headers being bad practice. If I am calling only one site ever with the HTTP client which in practice does happen using the DefaultRequestHeaders saves you from having to set them each time. – kmcnamee Jun 03 '18 at 23:24
  • 3
    @JCKödel, though you are incorrect in your assumption, I upvoted your comment, because you brought up an important point. Added greater clarity to the answer. – Najeeb Jan 14 '20 at 05:04
  • @kmcnamee, what if I need to pass two tokens? – Najeeb Jan 14 '20 at 05:15
87

The accepted answer works but can got complicated when I wanted to try adding Accept headers. This is what I ended up with. It seems simpler to me so I think I'll stick with it in the future:

client.DefaultRequestHeaders.Add("Accept", "application/*+xml;version=5.1");
client.DefaultRequestHeaders.Add("Authorization", "Basic " + authstring);
sirdank
  • 2,704
  • 2
  • 20
  • 45
  • 1
    Simplest way to add Basic Authorization header – sandyiit Jun 12 '20 at 17:07
  • But I call API one more time, that time I face error like Cannot add value because header 'Authorization' does not support multiple values. – Akash Limbani Apr 01 '21 at 05:03
  • 1
    @akash-limbani If you're reusing the same client, check before trying add. ``` if (!client.DefaultRequestHeaders.Contains("Authorization")) { client.DefaultRequestHeaders.Add("Authorization", "Basic " + authstring); } ``` – Rick Apr 13 '21 at 06:12
7

Following the greenhoorn's answer, you can use "Extensions" like this:

  public static class HttpClientExtensions
    {
        public static HttpClient AddTokenToHeader(this HttpClient cl, string token)
        {
            //int timeoutSec = 90;
            //cl.Timeout = new TimeSpan(0, 0, timeoutSec);
            string contentType = "application/json";
            cl.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
            cl.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", token));
            var userAgent = "d-fens HttpClient";
            cl.DefaultRequestHeaders.Add("User-Agent", userAgent);
            return cl;
        }
    }

And use:

string _tokenUpdated = "TOKEN";
HttpClient _client;
_client.AddTokenToHeader(_tokenUpdated).GetAsync("/api/values")
RDyego
  • 266
  • 1
  • 3
  • 6
6

You can add whatever headers you need to the HttpClient.

Here is a nice tutorial about it.

This doesn't just reference to POST-requests, you can also use it for GET-requests.

greenhoorn
  • 1,505
  • 2
  • 12
  • 34
  • 1
    [Github url](https://gist.githubusercontent.com/dfch/7b338046d5e63e3b3106/raw/b2c1bdb403906c7405472782ad1f4df580ba8a8d/HttpClient.cs), in case the site link expired. – Sen Jacob Mar 11 '20 at 05:41
5

Sometimes, you only need this code.

 httpClient.DefaultRequestHeaders.Add("token", token);
Jackdon Wang
  • 101
  • 1
  • 4