How do I set a cookie on HttpClient's HttpRequestMessage

C#Restasp.net Mvc-4asp.net Web-Api

C# Problem Overview


I am trying to use the web api's HttpClient to do a post to an endpoint that requires login in the form of an HTTP cookie that identifies an account (this is only something that is #ifdef'ed out of the release version).

How do I add a cookie to the HttpRequestMessage?

C# Solutions


Solution 1 - C#

Here's how you could set a custom cookie value for the request:

var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("foo", "bar"),
        new KeyValuePair<string, string>("baz", "bazinga"),
    });
    cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
    var result = await client.PostAsync("/test", content);
    result.EnsureSuccessStatusCode();
}

Solution 2 - C#

The accepted answer is the correct way to do this in most cases. However, there are some situations where you want to set the cookie header manually. Normally if you set a "Cookie" header it is ignored, but that's because HttpClientHandler defaults to using its CookieContainer property for cookies. If you disable that then by setting UseCookies to false you can set cookie headers manually and they will appear in the request, e.g.

var baseAddress = new Uri("http://example.com");
using (var handler = new HttpClientHandler { UseCookies = false })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var message = new HttpRequestMessage(HttpMethod.Get, "/test");
    message.Headers.Add("Cookie", "cookie1=value1; cookie2=value2");
    var result = await client.SendAsync(message);
    result.EnsureSuccessStatusCode();
}

Solution 3 - C#

For me the simple solution works to set cookies in HttpRequestMessage object.

protected async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken))
{
    requestMessage.Headers.Add("Cookie", $"<Cookie Name 1>=<Cookie Value 1>;<Cookie Name 2>=<Cookie Value 2>");

    return await _httpClient.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
}

Solution 4 - C#

After spending hours on this issue, none of the answers above helped me so I found a really useful tool.

Firstly, I used Telerik's Fiddler 4 to study my Web Requests in details

Secondly, I came across this useful plugin for Fiddler:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

It will just generate the C# code for you. An example was:

        var uriBuilder = new UriBuilder("test.php", "test");
        var httpClient = new HttpClient();


        var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uriBuilder.ToString());



        httpRequestMessage.Headers.Add("Host", "test.com");
        httpRequestMessage.Headers.Add("Connection", "keep-alive");
     //   httpRequestMessage.Headers.Add("Content-Length", "138");
        httpRequestMessage.Headers.Add("Pragma", "no-cache");
        httpRequestMessage.Headers.Add("Cache-Control", "no-cache");
        httpRequestMessage.Headers.Add("Origin", "test.com");
        httpRequestMessage.Headers.Add("Upgrade-Insecure-Requests", "1");
    //    httpRequestMessage.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        httpRequestMessage.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
        httpRequestMessage.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        httpRequestMessage.Headers.Add("Referer", "http://www.translationdirectory.com/");
        httpRequestMessage.Headers.Add("Accept-Encoding", "gzip, deflate");
        httpRequestMessage.Headers.Add("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8");
        httpRequestMessage.Headers.Add("Cookie", "__utmc=266643403; __utmz=266643403.1537352460.3.3.utmccn=(referral)|utmcsr=google.co.uk|utmcct=/|utmcmd=referral; __utma=266643403.817561753.1532012719.1537357162.1537361568.5; __utmb=266643403; __atuvc=0%7C34%2C0%7C35%2C0%7C36%2C0%7C37%2C48%7C38; __atuvs=5ba2469fbb02458f002");


        var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;

        var httpContent = httpResponseMessage.Content;
        string result = httpResponseMessage.Content.ReadAsStringAsync().Result;

Note that I had to comment out two lines as this plugin is not totally perfect yet but it did the job nevertheless.

DISCLAIMER: I am not associated or endorsed by either Telerik or the plugin's author in anyway.

Solution 5 - C#

I had a similar problem and for my AspNetCore 3.1 application the other answers to this question were not working. I found that configuring a named HttpClient in my Startup.cs and using header propagation of the Cookie header worked perfectly. It also avoids all the concerns about proper disposition of your handler and client. Note if propagation of the request cookies is not what you need (sorry Op) you can set your own cookies when configuring the client factory.

Configure Services with IServiceCollection
services.AddHttpClient("MyNamedClient").AddHeaderPropagation();
services.AddHeaderPropagation(options =>
{
    options.Headers.Add("Cookie");
});
Configure with IApplicationBuilder
builder.UseHeaderPropagation();
  • Inject the IHttpClientFactory into your controller or middleware.
  • Create your client using var client = clientFactory.CreateClient("MyNamedClient");

Solution 6 - C#

If you want to use HttpClient to send a request that require the user to be logged in, this means you need to do the login process then receive the cookies and send these cookies to the request that require login.

I did this in testing an Action called IsLoggedIn. This action checks if the user is logged using the cookies in the HttpRequest.

What I did in testing this action is:

                string Login = JsonConvert.SerializeObject(new LoginViewModel()
                {
                    Email = userFromDb.Email,
                    Password = "fdfdf@2239",
                    RememberMe = false
                }); ;
                StringContent LoginhttpContent = new(Login, Encoding.UTF8, "application/json");
                var Login_response = await _httpClient.PostAsync(HelperFunctions.getUrl(HelperFunctions.AcctounController.name, HelperFunctions.AcctounController.Login), LoginhttpContent);
                Assert.Equal(HttpStatusCode.OK, Login_response.StatusCode);
    
                //receive cookies from the login response
                var cookies = Login_response.Headers.GetValues(HeaderNames.SetCookie);
                 //Add the cookies to the DefaultRequestHeaders of the _httpClient
                _httpClient.DefaultRequestHeaders.Add("Cookie",cookies);
                var IsLoggedIn_response = await _httpClient.GetAsync(HelperFunctions.getUrl(HelperFunctions.AcctounController.name, HelperFunctions.AcctounController.IsLoggedIn));
                Assert.Equal("true",IsLoggedIn_response.Content.ReadAsStringAsync().Result);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorge MauerView Question on Stackoverflow
Solution 1 - C#Darin DimitrovView Answer on Stackoverflow
Solution 2 - C#Greg BeechView Answer on Stackoverflow
Solution 3 - C#Waqar UlHaqView Answer on Stackoverflow
Solution 4 - C#Amir HajihaView Answer on Stackoverflow
Solution 5 - C#KevMView Answer on Stackoverflow
Solution 6 - C#Kyrolus Kamal FahimView Answer on Stackoverflow