Connection closed from Facebook using http requests from ASP.net - asp.net

I'm trying to make some GETs to the Facebook rest api from an ASP.net core application, but I get every time an exception because the remote host closed the connection. I tried like fourty different solutions that I found in similar questions but none of them worked. I changed the security protocol to Tls 1.2 but still got the same issue; I also tried using web client instead of http client. Then I tought it might have been the proxy of my office but cUrl worked fine; using postman I didn't get any error (even with tsl set to 1.0).
Another attempt was to try changing the keep-alive duration to avoid time-outs.
Here's the code with the HttpClient:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
using (var httpClient = new HttpClient()){
httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
httpClient.DefaultRequestHeaders.Add("Keep-Alive", "3600");
var request = new HttpRequestMessage(HttpMethod.Get,
"https://graph.facebook.com/v10.0/me?fields=id%2Cemail%2Cfirst_name%2Clast_name&access_token=" + socialLoginModel.accessToken);
request.Headers.Add("Accept", "application/json");
request.Headers.Add("User-Agent", "BriQ");
var response = await httpClient.SendAsync(request);
}
And here's the code with the WebClient:
using(var wb = new WebClient()){
var response = wb.DownloadString("https://graph.facebook.com/v10.0/me?fields=id%2Cemail%2Cfirst_name%2Clast_name&access_token=" + socialLoginModel.accessToken);
}
I'm completely out of ideas. Maybe it's something really stupid that's causing the exception but I can't figure it out alone

I'm not sure about which exception that you exactly got.
But as far as I know, if you're using .NET Core and the problem is caused by the SSL/TLS handshake failure error, then, unfortunately, setting the ServicePointManager may not work...
Because the ServicePointManager only affects the HttpWebRequest which is the default implementation of HttpClient on .NET Framework. Starting with .NET Core 2.1, the SocketsHttpHandler provides the implementation used by HttpClient.
Hence, I suppose the way to fix the issue is handling the SocketsHttpHandler:
using (var handler = new SocketsHttpHandler())
{
handler.SslOptions = new SslClientAuthenticationOptions{EnabledSslProtocols = SslProtocols.Tls12};
using (var httpClient = new HttpClient(handler))
{
// your code
}
}
Alternatively, if you prefer HttpClientHandler, you could do in this way:
using (var handler = new HttpClientHandler())
{
httpClientHandler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
using (var httpClient = new HttpClient(handler))
{
// your code
}
}
Refs:
How to use TLS 1.2 in ASP.NET Core 2.0
HttpClient Class

Related

how to change dotnet core outgoing http request hostname from the default localhost

I am able to successfully send requests to a sandbox via postman, given by a provider following their specs (see images below)
Successful request (see below)
In order to do that, aside from the respective headers and parameters (see image 2) I have to add a ssl/Tls certificate (.pfx) given that the server requires a 2 way handshake so it needs SSl client certificate:
Authorization (see below).
Headers (see below)
Body (see below)
Now, I am trying to do ir programatically using dotnet core 6, but I keep running into the same problem:
And here is my code:
public static string GetAccessToken(IConfiguration _config)
{
string UserName = Environment.GetEnvironmentVariable("USER_NAME");
string Password = Environment.GetEnvironmentVariable("PASSWORD");
var client = new RestClient("https://connect2.xyz.com/auth/token");
var request = new RestRequest();
X509Certificate2 FullChainCertificate = new X509Certificate2("Path/to/Cert/cert.pfx", "test");
client.Options.ClientCertificates = new X509CertificateCollection() { FullChainCertificate };
client.Options.Proxy = new WebProxy("connect2.xyz.com");
var restrequest = new RestRequest();
restrequest.Method = Method.Get;
restrequest.AddHeader("Accept", "*/*");
restrequest.AddHeader("Cache-Control", "no-cache");
restrequest.AddHeader("Content-Type", "application/x-www-form-urlencoded");
restrequest.AddHeader("Authorization", "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes($"{UserName}:{Password}")));
restrequest.AddParameter("grant_type", "client_credentials");
RestResponse response = client.Execute(restrequest);
AccessTokenPointClickCare accessToken = JsonConvert.DeserializeObject<AccessTokenPointClickCare>(response.Content);
string strToken = accessToken.access_token;
return strToken;
}
Now, as the error seems to show, it has to do with the certificates (apparently), but I don't know if something in the code is wrong, or if I'm missing something, etc...
It is worth noting that this code did run in someone else's pc with the same set-up, but of course with that person's own pfx, but for the rest, it is essentially the same, and not to mention that it does work on my postman.
Finally, as the title on this question, the only thing I can think it might also be affecting the request is the host. If I reference the postman, there is a field where I have to place the host name of the server https://connect2.xyz.com/auth/token
So made it work by changing to a new Windows 10. Researching in other Stackoverflow threads found the answer: .NET CORE 5 '''HandshakeFailure'" when making HTTPS request
So I conclude it has to do with the cyphers

Using an asp web api in wpf

So i have got a simple question, when using our cms we can attach a driver as an executable.
The driver we want to make is an httpreceiver or just an api endpoint. SO i tought lets use asp.net web api for it -> using version .net 4.6.1. altough asp.net application requires a webserver and is not an executable, But i read on google you can use it inside a wpf application since our cms is wpf in the first place.
So my question is is there a way i can use my mvc web api project inside a wpf application? and if not what would be the best bet to have an httpreceiver or httppost receiver into an executable?
Main reason is we want to send httppost requests to the server as a desktop application. I know it's complicated but thats how it needs to be as far as I know.
In the case where asp is not an option, what the best way to make a postreqst/ httpreceiver as a desktop application?
EDit:
the resource guide from microsoft beneath was perfectly however i still have a question:
string baseAddress = "http://localhost:9000/";
// Start OWIN host
using (WebApp.Start<Startup>(url: baseAddress))
{
// Create HttpClient and make a request to api/values
HttpClient client = new HttpClient();
string username = "test".ToUpper().Trim();
string password = "test123";
//Mock data
var body = new PostTemplate1();
body.Description = "test";
body.StateDesc = "httpdriver/username";
body.TimeStamp = DateTime.Now;
body.Message = "This is a post test";
var json = JsonConvert.SerializeObject(body);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var authToken = Encoding.ASCII.GetBytes($"{username}:{password}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
var response = await client.PostAsync(baseAddress + #"api/Post", data);
var result = response.StatusCode;
}
As the guide says you post to url with port 9000
is there a possibility to use another port and use https?
if yes where to manage certificates for handling https?

Default Proxy in .NET Core 3.1

I need some help with .NET Core 3.1 for code that needs to get out of the corporate proxy. The code works in .NET 4.7.2 by putting the following in the app.config. This, I learned on this site (Thank you!), allows one to get through the corporate proxy server.
<system.net>
<defaultProxy useDefaultCredentials="true">
</defaultProxy>
</system.net>
The following code snippet works in .NET 4.7.2, and can get out past the proxy. The proxy is stored as an env variable named ALL_PROXY with a value of http:// our internal proxy:port (see [https://github.com/dotnet/corefx/pull/37238/commits/9ba8879ea104afac9dea9a78d3009b5bc700b7c3][1]). This is an Azure Cognitive service, so you will need a key vault, and a Cognitive Service.
var keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");
var kvUri = string.Format("{0}{1}{2}",
"https://",
keyVaultName,
".vault.azure.net");
var secretClient = new SecretClient(new Uri(kvUri),
new DefaultAzureCredential());
KeyVaultSecret secret = secretClient.GetSecret("FacesSubscription");
var subscriptionKey = secret.Value;
var credentials = new ApiKeyServiceClientCredentials(subscriptionKey);
var textClient = new TextAnalyticsClient(credentials)
{
Endpoint = endpoint
};
On .Net core, I get an http 407 exception.
Azure.RequestFailedException: 'Service request failed.
Status: 407 (ADAuth-AuthenticationFailed)
This exception occurs on the KeyVaultSecret line.
I have researched the issue #
[https://github.com/dotnet/corefx/pull/37238/commits/9ba8879ea104afac9dea9a78d3009b5bc700b7c3][1]
https://github.com/dotnet/corefx/pull/37238
https://github.com/dotnet/corefx/pull/37333
https://github.com/dotnet/runtime/issues/29147
and tried adding code such as
var handler = new HttpClientHandler();
handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
var httpClient = new HttpClient(handler);
I looked through the unit tests for the check-ins, but they all seemed to be about web proxies. The links above provide details of how the proxy is implemented.
Does anyone have idea around getting through a work proxy in NET Core with Azure services?
I have had a similar issue and this fixed it:
IWebProxy proxy = WebRequest.GetSystemWebProxy();
proxy.Credentials = CredentialCache.DefaultCredentials;
HttpClient.DefaultProxy = proxy;

API call returns 408 (Your POST request is not being received quickly enough. Please retry) but works fine with Postman and ajax

Calling an external API from asp.net core 2.2 with framework 4.6.1 using HttpClient always returns 408 with an error message Your POST request is not being received quickly enough. Please retry but same code works fine with pure asp.net 2.2. The external API also works fine when I use Postman or ajax.
Here is the API call -
using (var client = _httpClientFactory.CreateClient())
{
client.BaseAddress = new Uri("https://example.com/authenticate");
var response = await client.PostAsync(string.Empty, new JsonContent(data));
var content = await response.Content.ReadAsStringAsync();
return StatusCode((int)response.StatusCode, content);
}

ASP.Net Core HTTP Request Connections getting stuck

We have a simple application in ASP.NET Core which calls a website and returns the content. The Controller method looks like this:
[HttpGet("test/get")]
public ActionResult<string> TestGet()
{
var client = new WebClient
{
BaseAddress = "http://v-dev-a"
};
return client.DownloadString("/");
}
The URL which we call is just the default page of an IIS. I am using Apache JMeter to test 1000 requests in 10 seconds. I have always the same issue, after about 300-400 requests it gets stuck for a few minutes and nothing works. The appplication which holds the controller is completely frozen.
In the performance monitor (MMC) I see that the connection are at 100%.
I tried the same code with ASP.NET 4.7.2 and it runs without any issues.
I also read about that the dispose of the WebClient does not work and I should make it static. See here
Also the deactivation of the KeepAlive did not help:
public class QPWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
((HttpWebRequest)request).KeepAlive = false;
}
return request;
}
}
The HttpClient hast the same issue, it does not change anything
With dependency injection like recommended here there is an exception throw that the web client can't handle more request at the same time.
Another unsuccessful try was to change ConnectionLimit and SetTcpKeepAlive in ServicePoint
So I am out of ideas how to solve this issue. Last idea is to move the application to ASP.NET. Does anyone of you have an idea or faced already the same issue?

Resources