Issue: I am trying to use httpclient for fetching data from a site.Now the site requires you to first visit a link then only you can post data to the next link.
Link1 is a simple get request
Link2 is a post request
Now I think the site first store some cookie from the link1 and then only allow you to post data to link2 as whenever I try to open the link2 in incognito the site displays the error message "Session Timed out OR Maximum connections limit reached. Cannot Proceed Further. Please close and restart your browser "
Now I have tried this:
try
{
//Send the GET request
httpResponse = await httpClient.GetAsync(new Uri(link1UriString));
//Send the POSTrequest
httpResponse = await httpClient.PostAsync(new Uri(link2uriString),postContent);
httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
}
But I am getting the session timed out error message. How to maintain cookies for a session in httpClient continuously received from the web.Like in python it can be done by
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar()))
urllib2.install_opener(opener)
Link1
Link2
You can use a CookieContainer to handle cookies for you.
Doing so, you'd create the HttpClient like this.
using System.Net;
using System.Net.Http;
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient httpClient = new HttpClient(handler);
httpResponse = await httpClient.GetAsync(new Uri(link1UriString));
(Note it uses the version of HttpClient in System.Net.Http)
So, after first response you have Set-Cookie header:
var responseMessage = await httpClient.GetAsync("http://115.248.50.60/registration/Main.jsp?wispId=1&nasId=00:15:17:c8:09:b1");
IEnumerable<string> values;
var coockieHeader = string.Empty;
if (responseMessage.Headers.TryGetValues("set-cookie", out values))
{
coockieHeader = string.Join(string.Empty, values);
}
After that, just setup your cookie into request message:
var httpRequestMessage = new HttpRequestMessage
{
RequestUri = new Uri("http://115.248.50.60/registration/chooseAuth.do"),
Content = postContent,
Method = HttpMethod.Post
};
httpRequestMessage.Headers.Add("Cookie", values);
var httpResponse = await httpClient.SendAsync(httpRequestMessage);
Related
I am sending form data in a post request which I know returns cookies but my cookie variable is being returned as empty
I've tried using GetCookies as you can see but I'm wondering if I can filter the cookies out of my PostAsync Response as I get a 200 response
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
HttpContent content = new StringContent(JsonConvert.SerializeObject(formVals), Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(targetURI.AbsoluteUri , content);
IEnumerable<Cookie> responseCookies = cookies.GetCookies(targetURI).Cast<Cookie>()
foreach (Cookie cookie in responseCookies)
result.Add(cookie);
I expect 2 cookies to come back and be stored in my responseCookies Container
There are some unclear aspects in your question: where does your cookies variable come from, and where does your handler variable come from? These details are important to answer the question.
I can think of 2 possible wrong parts of your code. First, you should attach a CookieContainer to your handler:
var cookies = new CookieContainer();
var handler = new HttpClientHandler() { CookieContainer = cookies };
var client = new HttpClient(handler);
var content = new StringContent(JsonConvert.SerializeObject(formVals), Encoding.UTF8, "application/json");
var response = await client.PostAsync(targetURI.AbsoluteUri, content);
IEnumerable<Cookie> responseCookies = cookies.GetCookies(targetURI).Cast<Cookie>()
foreach (Cookie cookie in responseCookies)
result.Add(cookie);
Secondly (assuming your cookies and handler variables were initialized that way), you might need to fetch cookies for the correct base address (Uri.Host):
IEnumerable<Cookie> responseCookies = cookies.GetCookies(targetURI.Host).Cast<Cookie>()
If you are completely unsure, please check with this approach(deep inspection based on reflection) if cookies are set at all, and for which domain they are set.
Just so you guys know, the problem was I hadn't encoded my form data.
Changed content to the line below.
var content = new FormUrlEncodedContent(formVals);
I'm integrating a service that returns a key when I a GET request to a URL that is in the following format:
https://username:password#service.com/refresh.key
When I access the URL in my browser, it returns the new key as expected, by when I do a GET request using HttpClient I get a 401.
HttpClient _client = new HttpClient();
var response = await _client.GetAsync(#"https://username:password#service.com/refresh.key"); // Returns a 401
I think it has something to do with the '#' in the URL, but I'm not sure how to fix it, I tried replacing it with '%40', but when I do that I get a UriFormatException.
Does anyone know how to do this?
You should modify Authorization header of HttpClient, can you try the code below;
HttpClient _client = new HttpClient();
byte[] usernamePasswordBytes = Encoding.ASCII.GetBytes("user:pass");
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(usernamePasswordBytes));
var response = await _client.GetAsync(#"https://service.com/refresh.key");
PS: Such username:pass#domain.com requests are BasicAuthentication request so in fact you try to make basic authentication request.
Hope this works for you
You don't need to provide credentials in url. Instead you can do:
using (var handler = new HttpClientHandler {Credentials = new NetworkCredential("username", "password")}) {
using (HttpClient _client = new HttpClient(handler)) {
var response = await _client.GetAsync(#"https://service.com/refresh.key");
}
}
I am trying to get the URL of a page using HttpClient. I've previously only used HttpWebRequest, but I need to make this an async method.
In the code below, myUri always returns null which results in throwing an exception when I try to handle it later on.
Is the location header the wrong thing to be using?
string myUrl = "http://www.example.com/";
Uri myUri= new Uri(myUrl);
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(myUri))
{
if (response.IsSuccessStatusCode)
{
myUri= response.Headers.Location;
Debug.WriteLine("True "+ myUri);
}
else {
Debug.WriteLine("False " + myUri);
}
}
It's because HttpClient will automatically follows redirects. If you need the URL a page redirects to, you need to stop it from automatically following:
Change your code to the following:
string myUrl = "http://www.example.com/";
Uri myUri= new Uri(myUrl);
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClientHandler.AllowAutoRedirect = false;
using (HttpClient client = new HttpClient(httpClientHandler))
Here is an async way to resolve the final redirect URL:
public static async Task<string> ResolveFinalRedirectAsync(string url)
{
try
{
var req = WebRequest.CreateHttp(url);
req.AllowAutoRedirect = true;
var res = await req.GetResponseAsync();
return res.ResponseUri.AbsoluteUri;
}
catch
{
Console.WriteLine("Couldn't resolve '{0}'", url);
}
return null;
}
See #Rob's answer about AllowAutoRedirect.
Once you do that, note
The line
if (response.IsSuccessStatusCode)
evaluates to false if you receive a HTTP 301 redirect (anything outside of the 200-299 range)
A value that indicates if the HTTP response was successful. true if HttpStatusCode was in the Successful range (200-299); otherwise false.
(source)
OK thanks I'm trying to get redirected URLs anyway
If you prevent automatically following redirects, you will get an HTTP response in the 3xx range for the redirect. Your check for valid codes will have to be modified accordingly.
Using .NET Http client i login to jasper server.
HttpResponseMessage loginResponse = loginClient.PostAsync("http://localhost:8080/jasperserver/rest/login", formContent).Result;
IEnumerable<string> jaspsessid = loginResponse.Headers.GetValues("Set-Cookie");
Using above session id i pass to next request.
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Cookie", jaspsessid);
httpClient.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
StringContent requestContent = constructJasperRequestJson(reportParameters);
HttpResponseMessage generateReportRequestResponse = new HttpResponseMessage();
generateReportRequestResponse = httpClient.PostAsync(AppConstant.JASPER_SERVER_BASE_URI + AppConstant.JASPER_SERVER_REPORT_EXECUTION_URI, requestContent).Result;
In second request i am getting 401.Unauthorized.
If anyone knows the issue,help me.
You could use a CookieContainer to hold the session cookie, rather than setting a header.
See How do I set a cookie on HttpClient's HttpRequestMessage for an example.
I have a page on a site designed for adding a certain entity. What I'm trying to do is to add this entity using C# HttpClient. My sequence of steps looks like this:
First I'm authenticate using the client:
public static async Task<CookieCollection> WebPortalLogin(string baseURI, string phoneNo, string pin)
{
var cookies = new CookieContainer();
var handler = new HttpClientHandler()
{
CookieContainer = cookies
};
var client = new HttpClient(handler);
var content = new FormUrlEncodedContent(new[]{
new KeyValuePair<string,string>("page","login"),
new KeyValuePair<string,string>("noStaticBox",""),
new KeyValuePair<string,string>("username",phoneNo),
new KeyValuePair<string,string>("password",pin),
new KeyValuePair<string,string>("login","Увійти"),
new KeyValuePair<string,string>("_reqNo","0"),
});
var response = await client.PostAsync(baseURI, content);
response.EnsureSuccessStatusCode();
var stringResponse = response.Content.ReadAsStringAsync().Result;
var cookieJar = cookies.GetCookies(new Uri(baseURI));
return cookieJar;
}
Then I send POST request to edit page with all data I want to save:
public static async Task<HttpResponseMessage> AddCar(string baseURI, string phoneNo, CookieCollection cookieJar, string carNo, string owner)
{
var cookieContainer = new CookieContainer();
var client = new HttpClient(new HttpClientHandler() { CookieContainer = cookieContainer });
var content = new FormUrlEncodedContent(new[]{
new KeyValuePair<string,string>("carNo",carNo),
new KeyValuePair<string,string>("userName",owner),
new KeyValuePair<string,string>("page","carNumbers"),
new KeyValuePair<string,string>("submit","Додати"),
new KeyValuePair<string,string>("operation","addCar"),
new KeyValuePair<string,string>("_reqNo","0")
});
cookieContainer.Add(new Uri(baseURI), cookieJar);
var response = await client.PostAsync(baseURI, content);
var stringResponse = response.Content.ReadAsStringAsync().Result;
return response;
}
However, this POST request does nothing, and in response I have this very edit page, although when I add this entity in normal way (via web site), I get empty response and entity is successfully saved. Already checked cookies - they're all right. The only thing I can think of is request headers, but successful POST has only regular ones, like Accept, Accept-Encoding etc. What are my possible mistakes and how can I get it posted? Note: all connections use HTTPS.
ok, after messing a couple of hours I've discovered that the problem is in one of request parameters and not related to httpclient