C# HttpClient wont add Cookies from CookieContainer to request - c#

Cookies from CookieContainer are not added to Get or Post requests. Other headers work without a problem. What is the correct way to add cookies? I have done this before without a problem but I can't locate the error here.
var cookieContainer = new CookieContainer();
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.UseCookies = true;
handler.CookieContainer = cookieContainer;
var baseAddress = new Uri("https://www.example.se");
cookieContainer.Add(baseAddress, new Cookie("Testing", "Test"));
//This did not work either
//cookieContainer.Add(baseAddress, new Cookie("Testing", "Test", "/"));
using (var client = new HttpClient(new LoggingHandler(handler)))
{
client.BaseAddress = baseAddress;
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36");
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
client.DefaultRequestHeaders.Add("Accept-Language", "sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4");
var getResponse = client.GetAsync("/test").Result;
string responseString = getResponse.Content.ReadAsStringAsync().Result;
}
LoggingHandler:
https://stackoverflow.com/a/18925296/3850405

For some reason cookies aren't in the HttpRequestMessage headers when using CookieContainer. If I checked my CookieContainer object they were there though.
var cookieList = new List<Cookie>();
foreach (Cookie cookie in cookieContainer.GetCookies(baseAddress))
{
cookieList.Add(cookie);
}

Related

How to update the cookies in Httpclient instance which created via HttpClientFactory -C#

By using Httpclient straightly in .Net Console application, I can manage the cookies via below code:
HttpClientHandler handler = new HttpClientHandler();
CookieContainer cookieContainer = handler.CookieContainer;
using (HttpClient client = new HttpClient(handler) { Timeout = TimeSpan.FromMinutes(30) })
{
var urlLogin="http://xxxxxx";
var strContent="key=value"
await client.PostAsync(new Uri(url), new StringContent(strContent, Encoding.UTF8, "application/x-www-form-urlencoded"))
var cookie = cookieContainer.GetCookies(new Uri(url)).Cast<Cookie>().ToList();//get cookies
cookie[0].Path = "/";
cookieContainer.Add(cookie[0]); //update the first cookie path to avoid missing cookies in redirect request (302)
//other action
}
But in .Net core 3.1, I'm using HttpClientFactory to create HttpClient instance, initially I can add cookies with similar code as below when build HttpClient, but the handler is not accessible in the client instance, therefore I don't know how to update the cookie in the instance.
services.AddHttpClient("test1", c =>
{
c.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36");
c.Timeout = TimeSpan.FromHours(1);
}).ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler
{
CookieContainer = new CookieContainer(),
UseDefaultCredentials = true
}) ;
You can switch to HttpClient.SendAsync(HttpRequestMessage). In that case you create HttpRequestMessage instance for each request separately and then set cookie through HttpRequestMessage.Headers. Also you need to keep cookie value itself in some singleton class.
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent("content here", Encoding.UTF8, "application/x-www-form-urlencoded")
};
request.Headers.Add("Cookie", "your_value");
await _httpClientFactory.CreateClient().SendAsync(request);
So you set cookie per request and don't need to update it in clients.
Finally it was resolved:
Create a static variable
public class ScopedVars
{
public static HttpClientHandler staticHandler { get; set; } = new
HttpClientHandler();
}
In Setup, register it
services.AddScoped<ScopedVars>();
Add httpclient
services.AddHttpClient("TEST", c => {
c.DefaultRequestHeaders.Add("Accept", "/");
c.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT
10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"); c.Timeout =
TimeSpan.FromMinutes(5); }).ConfigurePrimaryHttpMessageHandler(_
=>ScopedVars.staticHandler);
In the service layer
private HttpClientHandler _handler; public
TestService(IHttpClientFactory httpClientFactory, ScopedVars
scopedHandler) {
_httpClientFactory = httpClientFactory; _handler = ScopedVars.staticHandler; }
In a specific task
CookieContainer cookieContainer = _handler.CookieContainer; using
(HttpClient client = _httpClientFactory.CreateClient("TEST")) {
//XXXX; }
Since I just run it as QuartzNet task, no need to worry about the multiple request.

HttpClient high data usage when getting remote file size

I'm getting the file size of remote urls and I just noticed the difference between HttpClient and httpWebRequest.
I compared and I noticed that httpclient is taking too much data.
this is a big issue for me because, in the Philippines we are only have limited data
Could you please tell me what's wrong with my httpclient class? I can't figure out what is causing the high data usage
HttpClient
HttpClientHandler handler = new HttpClientHandler()
{
Proxy = null,
UseProxy = false,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
var client = new HttpClient(handler);
client.DefaultRequestHeaders.Add("Method", "GET");
client.DefaultRequestHeaders.Add("Referer", uriPath.AbsoluteUri);
client.DefaultRequestHeaders.Add("Origin", "https://www.samplesite.com");
client.DefaultRequestHeaders.ConnectionClose = true;
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
using (HttpResponseMessage response = await client.GetAsync(uriPath, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
var resultTask = response.Content.ReadAsStringAsync();
var timeoutTask = Task.Delay(3000);
var completed = await Task.WhenAny(resultTask, timeoutTask).ConfigureAwait(false);
if (completed == timeoutTask)
return null;
return await resultTask;
}
HttpWebRequest
var webRequest = (HttpWebRequest)WebRequest.Create(uriPath);
webRequest.Method = "HEAD";
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36";
using (var webResponse = await webRequest.GetResponseAsync())
{
return await Task.Run(() => webResponse.Headers.Get("Content-Length"), token);
}
You are using different HTTP methods GET in case of HttpClient & HEAD in case of WebRequest. To get file size you will enough HEAD method in both cases
The HTTP GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
The HTTP HEAD method requests the headers that are returned if the specified resource would be requested with an HTTP GET method. Such a request can be done before deciding to download a large resource to save bandwidth, for example.
You need to change this code line
client.DefaultRequestHeaders.Add("Method", "GET");
it MUST BE
client.DefaultRequestHeaders.Add("Method", "HEAD");
A response to a HEAD method does not have a body in contradistinction to GET
UPD: use SendAsync method (not GetAsync)
HttpClientHandler handler = new HttpClientHandler();
using var client = new HttpClient(handler);
string requestUri = "enter request uri";
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Head, requestUri);
using var response = await client.SendAsync(message);
Finally it's solved Big thanks to #Dmitry
Here's the HttpClient updated code
public static async Task<string> GetTotalBytes(Uri uriPath)
{
HttpClientHandler handler = new HttpClientHandler();
handler.Proxy = null;
using (var client = new HttpClient(handler))
{
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Head, uriPath);
using (var response = await client.SendAsync(message))
{
response.EnsureSuccessStatusCode();
var lenght = response.Content.Headers.ContentLength;
return lenght.ToString();
}
}
}
RESULT (HttpClient):
Total URL: 355
Filsize: 1.14 GB
Elapsed Time: 0h 0m 2s 51.3ms
and here's HttpWebRequest (Maybe someone will need)
var webRequest = (HttpWebRequest)WebRequest.Create(uriPath);
webRequest.Method = "HEAD";
webRequest.Proxy = null;
using (var webResponse = await webRequest.GetResponseAsync())
{
return await Task.Run(() => webResponse.Headers.Get("Content-Length"), token);
}

C# HttpClient Authentication

I cant force to work HttpClient Post request...
or rather, I can't understand what I'm doing wrong..
My code below and this's sketch
#region Method 2
HttpClient h = new HttpClient();
var values = new Dictionary<string, string>
{
//{ "csrf_token" , "aacc347b22df2a7b3a20c9674ba59cf4279c8d16:1552967983844" },
//{ "track_id", "501c86f19b745703e9ca54991e90dc3a87" },
//{ "password", "Oguhokuu13" }
};
CookieContainer container = new CookieContainer();
h.DefaultRequestHeaders.Add("Accept", "application/json, text/javascript, */*; q=0.01");
h.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
h.DefaultRequestHeaders.Add("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
h.DefaultRequestHeaders.Add("Connection", "keep-alive");
h.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); // Content-Type
h.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("UTF-8"));
h.DefaultRequestHeaders.Add("Origin", "https://passport.yandex.ru");
h.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
// h.DefaultRequestHeaders.Add("Referer", "https://passport.yandex.ru/auth/welcome?retpath=https%3A%2F%2Ftaxi-cabinet.mobile.yandex.ru%2Fnews%2F");
h.DefaultRequestHeaders.Add("Host", "passport.yandex.ru");
h.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
var content = new FormUrlEncodedContent(values);
var response = h.PostAsync("https://passport.yandex.ru/auth/add", content);
response.Wait();
var responseString = response.Result.Content.ReadAsStringAsync().Result;
textBox1.Text = responseString.ToString();
#endregion
Then I get response:
\u001f?\b\0\0\0\0\0\0\u0003sN???/Q\b?\u000f\u000eQ?O,-??OLI?\u0002\0d(,h\u0016\0\0\0"
Idk what I'm doing wrong

Why I keep getting 401 from my webrequest code in C#

If I use a regular url it works fine and if I use google domains update url I get 401 error. This is my first try on C# application.
HttpWebRequest request = WebRequest.Create("https://UUUUUUUUUUUUU:PPPPPPPPPPPPP#domains.google.com/nic/update?hostname=subdomain.example.com") as HttpWebRequest;
//request.Accept = "application/xrds+xml";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.102 Safari/537.36 Viv/1.97.1246.7";
request.UseDefaultCredentials = true;
request.PreAuthenticate = true;
request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
WebHeaderCollection header = response.Headers;
var encoding = ASCIIEncoding.ASCII;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
string responseText = reader.ReadToEnd();
//responseddns = responseText;
MessageBox.Show(responseText);
}
If I use http://example.com/getip.php it works fine I can see the output.
you cannot use
> `CredentialCache.DefaultCredentials;`
since the url is the domain.google.com's domain.
You need to enter your google credentials or else directly use
http://example.com/getip.php as u did before

HttpClient is ignoring the `www.` part of the Request URI

I'm trying to send a GET request with HttpClient:
public static HttpClient Client { get
{
var handler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip };
var http = new HttpClient(handler) { BaseAddress = new Uri("https://www.example.com/") };
http.DefaultRequestHeaders.Accept.Clear();
http.DefaultRequestHeaders.Accept.TryParseAdd("*/*");
http.DefaultRequestHeaders.AcceptLanguage.TryParseAdd("en-US;q=0.6,en;q=0.4");
http.DefaultRequestHeaders.AcceptEncoding.TryParseAdd("gzip, deflate, br");
http.DefaultRequestHeaders.Host = "example.com";
http.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
http.DefaultRequestHeaders.Add("Connection", "keep-alive");
http.DefaultRequestHeaders.Add("Keep-Alive", "600");
http.DefaultRequestHeaders.UserAgent.TryParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36");
ServicePointManager
.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
return http;
}
...
using (var client = HttpHelper.Client)
using (var res = await client.GetAsync("api/stuff/filter?order=" + order + "&page=" + page))
if (res.IsSuccessStatusCode)
{
var json = await res.Content.ReadAsStringAsync();
var response = JsonConvert.DeserializeObject<AnimeResponse>(json);
return response;
}
Unfortunately this sends a request without the www. part and results in 301 status code as well as many, many failed redirects to the same address (without the www. part).
How can I fix this?
Edit: When I re-send the request with Fiddler it also returns 301, but the n it redirects correctly to wwww.. The HttpClient doesn't, and just redirects to the same www-less URI.

Categories