HttpClient.GetAsync works with LocalHost API, but not Live API - asp.net

I have a .Net 4.5.2 WebApp that is calling my API. When I point my web app to the LocalHost version of my API, it gets the data, and comes back just fine. I published that API, and confirm that the API is working correctly with PostMan.
Then I run the exact same WebApp code, changing only the URI from localhost to live api, and I get a multiple exception error consisting of the following:
An existing connection was forcibly closed by the remote host
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
The underlying connection was closed: An unexpected error occurred on a send.
An error occurred while sending the request.
Here's my calling code
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("user", serializedUser);
response = null;
try
{
//Uri uri = new Uri("https://jsonplaceholder.typicode.com/posts/1");//https works
Uri uri = new Uri("https://api.acme.com/values/test");
//Uri uri = new Uri("http://localhost/5000/values/test"); //http localhost works
response = client.GetAsync(uri).Result;
}
catch (Exception e)
{
string er = e.Message;
}
}
EDIT 1: I created a .NET Core app from scratch, and my original code works perfectly calling my live API. My original code also work in .NET 4.5.2 calling a different "https" API.
EDIT 2:
So this is where I'm at now, I have created two generic apps from VS 2015, one is a .NET Core Web App, the other a .NET Framework Web App. I have used the above code exactly the same in both apps to call the API. In both apps, I can call a generic "https" api I found online (jsonplaceholder). I can also call the localhost version of my app at "http" from both. In the .NET Core version of the app, I can call my "https" live API and get the results I'm looking for. In the .NET Framework app I still get the same errors.
I can't figure out what the difference is between my Core and Framework requests that is getting one shut down when the other isn't.

It seems you are hosting the application on secured http environment (https). Are you using SSL certificate on the server where you are hosting your Web API? If not, It might be throwing the certificate related exceptions.
Just add the following line before the call to GetAsync and This will ignore the SSL errors.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
This is only recommended in an intranet environment or other closed network where server identities can't be forged.
C# Ignore certificate errors?

Adding the following line before my API call fixed the issue, but I'd love to hear an explanation of what this line does, and any security risks this might impose using it in my web app.
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Props to this answer!

Related

Blazor Webassembly, custom http response headers

I'm creating Blazor Webassembly app, which call my Dotnet web API. I'm using the injected http client, and the api call itself run without problems, Postmann & WireShark confirms that my custom response headers from the API is returned correctly. But in the Blazor Webassembly app, there is only one header "content-type". I know that the Blazor Http client is a wrapper around some Javascript, but are there anyone out there that can help with some knowledge or examples on how to get custom response headers thru to the Blazor app.
I'm using Visual Studio 2019 Community and also Visual Studio Code, and normally I develop on a Mac, but due to problems with debugging Blazor apps on Mac I changed to Windows 10.
It was actually very simple. To allow my custom response headers to be available in a Blazor Webassembly app, On the server API, just add below header to the response:
HttpContext.Response.Headers.Add(" Access-Control-Expose-Headers","YourCustomHeader,YourOtherCustomHeader");
As #Jagdriver mentioned, adding:
HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "my-header");
will add an extra header to the response in order to indicate which headers may be processed, additionally to the safe headers.
About .NET, the headers can be retrieved into a dedicated property of the response:
HttpClient http = new();
HttpResponseMessage response = await http.GetAsync("https://...");
string MyHeader = "my-header";
KeyValuePair<string, HeaderStringValues> nvHeaders =
response.Headers.NonValidated
.Where(v => v.Key == MyHeader)
.FirstOrDefault();
// KeyValuePair is a struct, default value is a KeyValuePair where the Key is null.
if (!string.IsNullOrEmpty(nv.Key))
{
string MyHeaderValue = nv.Value.FirstOrDefault();
}

Wordpress api not allowing rejecting server-side connection

I'm trying to connect to our wordpress api in our asp.net mvc application, using the following code
public static string GetLifespeakBlogListings()
{
WebClient client = new WebClient();
string url = "https://lifespeak.com/wp-json/wp/v2/posts?categories=6";
string listings = client.DownloadString(url);
return listings;
}
however I'm getting the following exception :
System.Security.SecurityException Failed to negotiate HTTPS connection with server.fiddler.network.https> HTTPS handshake to lifespeak.com (for #1) failed. System.IO.IOException Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
If I access this feed from a browser, it works fine https://lifespeak.com/wp-json/wp/v2/posts?categories=6
However, if I try from fiddler, I get the same exception:
I'm assuming that something on our wordpress site is blocking this request for some reason. Is there something I can configure to prevent this? How can I determine the cause?
The issue was that the version of System.Net I was using in my application was attempting to make the request to the wordpress API using TLS 1.0, and was getting rejected, similar to the issue with fiddler that dave pointed out above. I fixed this by adding the following line of code in the method, as specified in How to specify SSL protocol to use for WebClient class
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Note that the value has to be added manually and cast as a SecurityProtocolType, as .net 4.0 (the version I was using) doesn't support tls1.2

Windows 8.1 application does not do the NTLM Negotiation required by Windows Authentication

I have a Windows 8.1 Store application that I side-load on a Windows 10 Enterprise DELL tablet. The app uses data from a repository via an ASP.NET Web API installed on a remote server. The Web API is configured to use Windows Authentication. If I use Fiddler to make Web API calls I can see the several steps in the NTLM negotiation, the 401.2 HTTP Error messages returned twice before the HTTP 200 Ok.
However, my application gets the 401.1 and then it does not do anything else. In my application's package manifest, I have checked Enterprise Authentication check box in the list of required capabilities. Also, when I tested it with the Visual Studio Simulator, on my development machine, the negotiation was done and the Web API responded properly to my calls.
In order to have the NTLM Negotiation done automatically in the background, I though all that needs to be done is to have an HttpClientHandler object constructed like this:
var webApiAuthClientHandler = new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials,
ClientCertificateOptions = ClientCertificateOption.Automatic
};
Then, this HttpClientHandler object would be passed in the constructor of the HttpClient object used to make the Web API calls:
var webApiHttpClient = new HttpClient(webApiAuthClientHandler)
{
BaseAddress = new Uri(_myWebApiUri, UriKind.Absolute),
Timeout = new TimeSpan(0, 0, 150)
};
What am I missing? How do I get my app to automatically negotiate the authentication in the background and have my GetAsync call return the needed HTTP Code 200?
Any suggestion would be highly appreciated.
TIA,
Eddie
I see your issue has been resolved in MSDN forum: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/58620579-240d-49da-8538-cee5aff91a68/w81-sideloaded-windows-81-application-generates-an-exception-when-calling-methods-of-an-restful?forum=wpdevelop
So I post it here to help more visitors find the solution easily.
Thank you.

Trusting an IIS self-issued certificate

So I'm using a self-signed certificate on my localhost for HTTPS.
I'm running my Web Api 2 web service on it for testing while I develop a client website that links into the api but the client website can't establish a connection with the api because of trust issues concerning the certificate is self-signed and thus, not to be trusted.
Here's what Firefox says when I browse to the web service:
The client website is developed using MVC. So far I'm using WebClient to query data from the web service.
The code I'm currently working on to access the web server is a simple login. The MVC site sends the login data to the web service which uses it to select a record from the database. It sends the record back to the MVC site if it gets one.
Here's the code:
private bool DoLogin(string EmailAddress, string Password)
{
WebClient client = new WebClient();
NameValueCollection credentials = new NameValueCollection
{
{ "EmailAddress", EmailAddress },
{ "Password", Password }
};
client.QueryString = credentials;
string result = client.DownloadString(new Uri("https://localhost/mywebservice/api/User/"));
// just return true so we can debug to see values
return true;
}
Currently I'm only getting a non-descript WebException that just says "Internal Server Error" (Status Code 503).
Its my understanding now that I need to use a certificate that isn't self-signed, but I can't create one in IIS. I'm trying to create a domain certificate but I'm confused about the Certification Authority and from what I understand, this isn't going to help me get my web app to accept the certificate anyway.
Anyway, as an alternative, I'm looking at this MSDN blog and I've done all those things to get it right (see screenshot below) but it doesn't seem to have helped anything as I still get the untrusted connection screen in my browser.
I'm pretty much at a loss what I should do now...

Unable to set proxy for SignalR HubConnection

Using version 2.0 for Asp.NET SignalR, we have created a prototype application that has a WPF client application and a web site that has SignalR configured. This prototype works correctly when run on the local developer computer and when the web site was deployed to an internal development server.
An issue that has been encountered once the web site was deployed to an external server; the following exception is encountered when the HubConnection.Start method is called:
HttpClientException
A first chance exception of type 'Microsoft.AspNet.SignalR.Client.HttpClientException' occurred in mscorlib.dll
Additional information: StatusCode: 407, ReasonPhrase: 'Proxy Authentication Required ( Forefront TMG requires authorization to fulfill the request. Access to the Web Proxy filter is denied…
The network that the developer computer is on requires the use of a proxy to reach the Internet. The web site that has the SignalR component also has some WCF endpoints; these can be connected to using the HttpClient within the WPF client application when the proxy is set in code. The same approach to set the proxy was done on the HubConnection but the error is encountered.
Below is code on how the proxy is set to the HubConnection; the same credentials work when accessing the other, non-signalR, endpoints:
var proxyInfo = new WebProxy(new Uri(“theAddress”));
proxyInfo.Credentials = new NetworkCredential(“theUserName”, “thePassword”, “theDomain”);
hubConnection.Proxy = proxyInfo;
Is there something else that has to be set with the HubConnection for it to use the proxy?
Thanks,
Scott
The issue is that there is a bug with the 4.5 .NET Client for SignalR; the proxy information is not being sent with the requests in the HubConnection. This is a regression from the 1.0 release.
The link below contains the information:
https://github.com/SignalR/SignalR/issues/2856

Resources