Using HttpClient in new WebApi project - c#

I have created a new Webapi2 project and I am trying to call an external web service using this code:
WebServiceAuthResult authResult = new WebServiceAuthResult();
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
try
{
var response = await httpClient.PostAsync(url, null);
var responseContent = await response.Content.ReadAsStringAsync();
authResult = JsonConvert.DeserializeObject<WebServiceAuthResult>(responseContent);
}
catch (Exception ex)
{
}
}
I am getting this error:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
I have used the exact same code in a UWP project and it works perfectly - So I am guessing there's something wrong in my project set up.
I've looked at Google and other StackOverflow questions about this but they all suggest an issue with the web service - but I know this is working as I can test using my UWP project.
Can anyone suggest anything for me to try?

As is usually the case with these questions the answer is a one liner but has taken 4 hours to resolve!
By adding this line of code the connection to the web service is successful:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
I've added the code in the using statement but I think it's only required once so if anyone can tell me where is the best place to add this code and why I need it in my WebApi project and not my UWP project?

Related

How can I log Get/Patch/Post statements being sent from my .NET library project?

I'm not sure there is anything wrong with my code, but I have a dll .net 4.8 library file that is hooked up to an ERP system that makes REST calls to a third party web based app that is unix-based. We are troubleshooting an issue regarding a strange error but something else came up where they said they are getting a lot of GET statements from the dll for URLs that require PATCH/POST and those urls (specifically one) doesn't have functionality set up for a GET statement.
Is is possible that the .NET objects are sending underlying HTTP calls?
So basically, I would like to log all of the REST statements that are being sent to verify, if possible, where they are coming from. I've combed my code and there is literally one entry point to this statement and I am sending a PATCH and the resource url doesn't require anything to be sent in the body except an empty string.
So is there a way to log all the HTTP calls going out from my project? See code below for my routine.
I've looked up how to log and I mostly get results for web projects, but this is a dll project and I'm not sure if those suggestions will work for this.
try
{
CVToken curToken = CVGlobalRestCalls.GetToken(Session);
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", curToken.Token);
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var jSettings = new JsonSerializerSettings();
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), string.Format("{0}/readytosend/{1}/complete", Globals.GetRESTURL(Session), JobID));
request.Content = new StringContent(JsonConvert.SerializeObject(string.Empty, Formatting.Indented, jSettings), Encoding.Default, "application/json-patch+json");
HttpResponseMessage response = httpClient.SendAsync(request).Result;
CVJob cvCompletedJob = JsonConvert.DeserializeObject<CVJob>(CVGlobalRestCalls.GetResponseContent(response));
outFile.WriteLine(string.Format("Invoice Group {0} has been pushed to CV", JobID.ToString()));
}
catch (Exception ex)
{
throw new Exception(string.Format(" {0}", ex.Message));
}

Adding SSL cert causes 404 only in browser calls

I am working in an internal corporate environment. We have created a webapi installed on iis on port 85. We call this from another MVC HelperApp on port 86. It all works as expected. Now we want to tighten security and add an SSL cert to iis on port 444 and bind it to our API.
Initially we test it with Postman, SoapUI, and a C# console app and it all works. Now we try calling it from our MVC HelperApp and it returns a 404 sometimes.
Deeper debugging; I put the code into a C# DLL (see below). Using the console app I call the Dll.PostAPI and it works as expected. Now I call that same Dll.PostAPI from the MVC HelperApp and it won't work. When I step through the code I make it as far as this line await client.PostAsync(url, data); and the code bizarrely ends, it doesn't return and it doesn't throw an exception. Same for Post and Get. I figure it makes the call and nothing is returned, no response and no error.
Also, if I change the url to "https://httpbin.org/post" or to the open http port85 on iss it will work. I have concluded that the C# code is not the problem (but I'm open to being wrong).
Therefore I have come to the conclusion that for some reason the port or cert is refusing calls from browsers.
We are looking at:
the "Subject Alternative Name" but all the examples show
WWW.Addresses which we are not using.
the "Friendly Name" on the cert creation.
and CORS Cross-Origin Resource Sharing.
These are all subjects we lack knowledge in.
This is the calling code used exactly the same in the console app and the web app:
var lib = new HttpsLibrary.ApiCaller();
lib.makeHttpsCall();
This is what's in the DLL that gets called:
public async Task<string> makeHttpsCall()
{
try
{
List<Quote> quotes = new List<Quote>();
quotes.Add(CreateDummyQuote());
var json = JsonConvert.SerializeObject(quotes);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var url = "https://httpbin.org/post"; //this works in Browser
//url = "https://thepath:444//api/ProcessQuotes"; //444 DOES NOT WORK in browsers only. OK in console app.
//url = "http://thepath:85/api/ProcessQuotes"; //85 works.
var client = new HttpClient();
var response = await client.PostAsync(url, data); //<<<this line never returns when called from browser.
//var response = await client.GetAsync(url); //same outcome for Get or Post
var result = await response.Content.ReadAsStringAsync();
return result;
}
catch (Exception ex)
{
throw;
}
}

Xamarin.Forms iOS throwing NSURLErrorDomain "internet connection offline" when device is online

When calling a request from the HTTP manager the application throws an NSURL Error that states the internet connection is offline.
Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline."
This is only happening sometimes and every time that it is happening the device has internet access.
Upon attempting to debug the solution it seems that the rest service call for client.GetAsync isn't returning a response.
public async Task<T> callGetAsync<T>(string path) {
using(var client = new HttpClient()) {
var result = default(T);
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (App.User.Context != null)
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", App.User.Context.AccessToken);
}
HttpResponseMessage response = await client.GetAsync(path);
if(response.IsSuccessStatusCode) {
string json = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<T>(json);
}
else {
Console.WriteLine("Error");
Analytics.TrackEvent($"API Failure: {path}");
}
return result;
}
}
The expected result is the application should successfully make the call and return the desired results, instead the application is suggesting the internet connection is offline.
Has anyone else seen this behavior? If so, have you been able to solve it?
This has been reported to be an issue with Visual Studio Preview builds. Downgrading back to the latest stable release has fixed the issue for now.
https://github.com/xamarin/xamarin-macios/issues/6762#issuecomment-524016733
I found this and Visual Studio 2019 is long out of preview. Looking up this error in different places. I read "Check the URL that you are using and make sure that is correct" and thought of course it is. I was wrong. So this is a friendly reminder. Check your pride and the URL :) Don't worry I made the same mistake.

C# clickatell to send SMS HTTP GET request

I want to send a simple message using the service Clickatell.
I don't want to read the response, it will be simple GET request to send a message.
The service provides the request looks like:
https://platform.clickatell.com/messages/http/send?apiKey=xxxxxxxxxxxxxxxx==&to=xxxxxxxxxxx&content=Test+message+text
I checked it with curl
curl "https://platform.clickatell.com/messages/http/send?apiKey=apiKEY==&to=NUMBER&content=Test+message+text"
and it's working really fine.
I try to use it with my Windows Forms application with HTTP request
Below is the code which I provided:
var client2 = new HttpClient();
client2.GetAsync("https://platform.clickatell.com/messages/http/send?apiKey=apiKEY==&to=NUMBER&content=Test+message+text");
App.Write("SMS SEND!");
I have info that SMS send, but I didn't receive it. My friend use my code in the .NET application and it's working for him.
Do I miss something?
Maybe it's really worth to mention I need to add to References manually using System.Net.Http;
EDIT:
I tried to add to do it async, so I edit my code to:
static void sendSMS()
{
var client2 = new HttpClient();
var task = client2.GetAsync("https://platform.clickatell.com/messages/http/send?apiKey=API_KEY==&to=MY_NUMBER&content=Test+message+text");
task.Wait();
App.Write("SMS SEND!");
}
But now the SMS SEND message in the application is not shown.
Ok I know You use .NET 4.5 and You probably have problem with a exeption
"The underlying connection was closed: An unexpected error occurred on a send"
The right code it looks like this: (You must add 'SecurityProtocol 'before reqeust):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
var client2 = new HttpClient();
client2.GetAsync("https://platform.clickatell.com/messages/http/send?apiKey=apiKEY==&to=NUMBER&content=Test+message+text").Result;
More details herehttps://stackoverflow.com/a/32789483/5816153

Downloading webpages in WinRT throws an exception

I'm using this code to download a web page in my Metro Style app:
public static async Task<string> DownloadPageAsync(string url)
{
HttpClientHandler handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
handler.AllowAutoRedirect = true;
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsString();
return responseBody;
}
the problem is that when the line client.GetAsync(url) runs, it throws an exception that says:
An error occurred while sending the request. From type: HttpRequestException.
EDIT:
I've used the InnerException to get more info. The first exception thrown is SocketException with the message below:
An attempt was made to access a socket in a way forbidden by its access permissions
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
EDIT 2:
I've downloaded and ran the sample from Microsoft and I get the same error:
http://code.msdn.microsoft.com/windowsapps/HttpClient-Upload-Sample-f1abcc4e
EDIT 3:
I ran this on another machine and it worked fine. So I guess there's nothing wrong with the code. I copied the solution and it means that there's nothing wrong with the solution either. I'm trying to re-install Windows Developer Preview to see if it fixes my problem.
OK. I found the answer. The exception was because I installed NetLimiter product on Windows 8 Developer Preview and somehow it prevented my app from accessing the internet.
UPDATE:
First of all, this is the code working in EVERY version of Windows 8.
public static async Task<string> DownloadPageAsync(string url)
{
try
{
HttpClientHandler handler = new HttpClientHandler { UseDefaultCredentials = true, AllowAutoRedirect = true };
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string html = await response.Content.ReadAsStringAsync();
return html;
}
catch (Exception)
{
return "";
}
}
Secondly, if this doesn't work, chances are, you have a network-related software preventing your app to access the Internet. One popular case is proxifier. If you have proxifier installed your MetroStyle apps won't be able to access the internet. To make it work, please refer to my blog at:
http://anoori.me/blog/general/use-proxifier-in-windows-8-without-fiddler2
pretty sure netlimiter was running your internet request through a localhost proxy, and your app didn't have the "local network" capability which would allow such access to the local network

Categories