HttpRequestMessage is null in HttpClientHandler.ServerCertificateCustomValidationCallback - c#

I am attempting to use the ServerCertificateCustomValidationCallback of HttpClientHandler but the value of the request parameter is always null. Is this expected behavior or do I need to set a bit somewhere?
For example the following snippet results in printing Request not defined 4 times.
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (_request,_certificate, _chain,_errors) =>
{
Console.WriteLine(_request?.RequestUri.ToString() ?? "Request not defined");
return true;
};
var client = new HttpClient(handler);
var request = new HttpRequestMessage(HttpMethod.Get, "https://google.com");
client.SendAsync(request);
client.GetAsync("https://google.com");

Related

Send HTTP Request doesn't work with WebProxy

I'm scraping data from some sites and one of theses use headers for some information. I'm using Smart Proxy Manager from Zyte and having problems with a request with headers. When I use the zyte proxy, I receive a response, but the site that I'm scraping return an unsuccess message. If I not use the proxy, the request works like a charm. Can anyone help me?
Here is my code
string zyteKey = _configuration["ZyteKey"];
var proxy = new WebProxy("myproxy");
proxy.Credentials = new NetworkCredential(zyteKey, "");
var clientHandler = new HttpClientHandler()
{
Proxy = proxy,
UseProxy = true,
PreAuthenticate = true,
AllowAutoRedirect = false
};
using (var client = new HttpClient(clientHandler))
{
string json = JsonConvert.SerializeObject(jsonObject);
var content = new StringContent(json, Encoding.UTF8, "application/json");
client.Timeout = new TimeSpan(0, 1, 0);
client.DefaultRequestHeaders.Add("cookie", BuildCookieRequest(latitude, longitude, restaurantName));
client.DefaultRequestHeaders.Add("Accept", "application/json, text/plain, */*");
client.DefaultRequestHeaders.Add("x-csrf-token", "x");
return await client.PostAsync(url, content);
}

Not able to get certificate from HttpContext which was send from HttpClient

Well, I tried many different solutions but none seems to be working.
I have created Self Signed Certificate from IIS Manager and also import this to cert store.(Current User\Personal\Certificates). I tried to send that cert using below code part:
var cert = new X509Certificate2(#"C:\\Test.pfx", "asdf");
var handler = new HttpClientHandler() { ClientCertificateOptions = ClientCertificateOption.Manual };
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44351/helloworld"),
Method = HttpMethod.Get,
};
var response = client.SendAsync(request).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}
But I when tried to receive it, it consists of null.
var clientCertificate = httpContext.Connection.ClientCertificate;
I think there exist some underlying concepts which I am not able to find out.

HttpClient throws error with the Rest services

I am trying to call multiple rest services from the Web API I am creating and I am getting the below error while one of the Sharepoint rest service is called
This instance has already started one or more requests. Properties can only be modified before sending the first request.
Below is the code for calling the rest services using the HttpClient
try
{
var credential = new NetworkCredential(userName_SP, password_SP, domain_SP);
var myCache = new CredentialCache();
myCache.Add(new Uri(core_URL), "NTLM", credential);
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.Credentials = myCache;
using (var client_sharePoint = new HttpClient(handler))
{
var response = client_sharePoint.GetAsync(core_URL).Result;
client_sharePoint.BaseAddress = uri;
client_sharePoint.DefaultRequestHeaders.Accept.Clear();
client_sharePoint.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var responsedata = await response.Content.ReadAsStringAsync();
var returnObj = JsonConvert.DeserializeObject<SharepointDTO.RootObject>(
responsedata);
return returnObj;
}
...
I have never encountered this error before. Can anyone please suggest me if I need set the timeout
Try this:
var credential = new NetworkCredential(userName_SP, password_SP, domain_SP);
var myCache = new CredentialCache();
myCache.Add(new Uri(core_URL), "NTLM", credential);
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.Credentials = myCache;
using (var client_sharePoint = new HttpClient(handler))
{
client_sharePoint.BaseAddress = uri;
client_sharePoint.DefaultRequestHeaders.Accept.Clear();
client_sharePoint.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client_sharePoint.GetAsync(core_URL);
var responsedata = await response.Content.ReadAsStringAsync();
var returnObj = JsonConvert.DeserializeObject<SharepointDTO.RootObject>(
responsedata);
return returnObj;
}
Headers and BaseAddress must be set before you make the request with GetAsync.
I also took the liberty to change from .Result to await since calling .Result is poor practice and I can see this is in an async method.
You should also read this: https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

How do I add the profile parameter to the content-type header in C#?

I'm trying to set the content-type of my HttpClient Post request, and use the profile parameter, but when I change the content type I get an exception thrown:
"The format of value 'application/json; profile={URL HERE}' is
invalid."
For reference, I found this Q&A: Zoopla Sandbox with cURL http header error
X509Certificate2 cert = new X509Certificate2("cert.pfx", "PASSWORD");
WebRequestHandler handler = new WebRequestHandler();
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://realtime-listings-api.webservices.zpg.co.uk");
var stringContent = new StringContent(propertyData, Encoding.UTF8, "application/json; profile=http://realtime-listings.webservices.zpg.co.uk/docs/v1.1/schemas/listing/list.json");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var response = await client.PostAsync("/sandbox/v1/listing/list", stringContent);
return _resultFactory.Create(true, await response.Content.ReadAsStringAsync());
If you create a HttpRequestMessage and use client.SendAsync(), you can add the parameters to request.Content.Headers.ContentType.Parameters
var client = new HttpClient();
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://realtime-listings-api.webservices.zpg.co.uk/sandbox/v1/listing/list"))
{
request.Content = new StringContent("propertyData", Encoding.UTF8, "application/json");
request.Content.Headers.ContentType.Parameters.Add(
new NameValueHeaderValue("profile", "http://realtime-listings.webservices.zpg.co.uk/docs/v1.1/schemas/listing/list.json")
);
var response = await client.SendAsync(request);
//Handle response..
}
You don't need to use HttpRequestMessage but you do need to add the profile value as a quoted string via the NameValueHeaderValue parameter:
var content = new StringContent(request.ToJson(), Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("profile", "\"https://realtime-listings.webservices.zpg.co.uk/docs/v1.2/schemas/listing/update.json\""))
httpClient.PostAsync("listing/update", content);
This will get round the FormatException. Otherwise you will run into this dotnet bug.

Read cookie in WPF application

in a wpf application I have to call an external rest service which returns a cookie with session id in it. In all subsequent calls I have to send session id in cookie otherwise it does not return any data.
So how can I retrieve the cookie in wpf code behind class?
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
var domain = EndPoint;
HttpResponseMessage response2 = client.PostAsync(domain, new StringContent(parameters)).Result;
Uri uri = new Uri(domain);
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
var cookieWithId = responseCookies.Single(o => o.Name == "JESSSIONID");
where EndPoint has http://mydomain.com:38080/workshop/ and parameters has rest/login?username=usr&password=pwd
Here's an example on how to read cookies from response.
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
var domain = "http://yourServiceURL.com";
HttpResponseMessage response = client.GetAsync(domain).Result;
Uri uri = new Uri(domain);
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
var cookieWithId = responseCookies.Single(o => o.Name == "SessionId");

Categories

Resources