SendAsync is not working from an External server (Web API2) - c#

We are running into a situation where sendAsync post call from a server is not working. Here's my scenario
We have a Web API hosted on a server outside our internal network (DMZ) which has a simple GET implemented to it as
Public HttpResponseMessage Get(strind id){ (API 1)
//do some work
using(HttpClient client = new HttpClient()){
//We Invoke another web API which is hosted inside our network and do a post // as
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url);
message.Content = new StringContent(someStr);
message.Content.Header.ContentType = new MediaTypeHeaderValue("application/json");
try{
var response = client.SendAsync(message).Result (API 2)
}
catch(Exception e){
//Something
}
}
The post SendAsync().Results fails with the following exception
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) and the message says as One or More errors Occurred.
The innerexception is also not telling anything good. It just InnerException.StackTrace is coming blank and the InnerException.Message is An error occurred while sending request.
In order to test the communication, we ran a GET request from the external sever for API 2 and it worked fine but the POST's are not working.
Everything works fine when both the API's (the one for get and the other one that does the post) are hosted on our internal servers.
Any Suggestions why this might not be working when executed from the external server?

Short answer: Regardless of what I'm betting on, you have to inspect those inner exceptions and find out the exact message.
Longer answer:
The fact that when you host the application in your internal network, the code works (the POST call is successful) and when moved to DMZ it fails strongly indicates the server making the call has no access to the remote endpoint.
I'd bet on the lack of network connectivity between your App Server and the API 2.

Related

RestSharp Response error: "Only one usage of each socket address (protocol/network address/port) is normally permitted"

I'm using RestSharp to communicate with a .Net Core Web API. Both Client and Server are written by me.
I have a suite of Services all inheriting a Base class which contains an async method to perform the request via a RestClient. Here is the method within the base class that creates the RestClient.
private async Task<ServiceResponse> RequestAsync(ServiceRequest request)
{
try
{
var result = await new RestClient(_digiCore.Config.GetApiBaseUrl()).ExecuteTaskAsync(request.Request, request.CancellationTokenSource.Token);
switch (result.StatusCode)
{
case HttpStatusCode.OK:
case HttpStatusCode.Created:
case HttpStatusCode.NoContent:
return new ServiceResponse
{
Code = ServiceResponseCode.Success,
Content = result.Content
};
// User wasn't authenticated for this one - better luck next time!
case HttpStatusCode.Unauthorized:
Logger.LogError($"Unauthorized {request.Method.ToString()}/{request.Path}");
default:
Logger.LogError($"An error occurred {request.Method.ToString()}/{request.Path}");
}
}
catch (Exception e)
{
Logger.LogError($"A Rest Client error occurred {request.Method.ToString()}/{request.Path}");
}
}
My understanding is that the RestClient (unlike HttpClient) is thread safe and OK to create a new instance each time.
When Load testing my application, one I reach a certain point, I find that I occasionally receive the following response back from the API. Refreshing the page might bring back the correct result, or I might get another error. When the Load Test has finished everything goes back to normal. The numbers of the load test are nothing crazy, so its started to get me worried about real-life performance...
Only one usage of each socket address (protocol/network address/port) is normally permitted
I believe this is down to port exhaustion. Both API and Client are running in Azure as App services.
I have tried making the RestClient part of a singleton service, and checked that it is only created once - but this did not alleviate the issue.
I have also looked into setting the DefaultConnectionLimit in the Startup function of my startup class from the default (2) to 12, but I did not see any improvements here either.
I'm really struggling to see how I can improve this...
Found out the reason for this...
It seems there is currently an issue with RestSharp whereby socket connections are not closed down immediately and instead are left in TIME_WAIT state.
This issue is currently logged with the RestSharp guys here ->
https://github.com/restsharp/RestSharp/issues/1322
I have chosen to switch over to using HttpClient - and running the exact same load test I had zero problems.
Here is an screenshot taken from Azure showing the difference between the two load tests.
Was with my app using RestSharp
Was with my app using Http Client
Hope this helps somebody. It's a shame I had to ditch RestSharp as it was a nice little library - unfortunately with an issue like this it's just too risky to run in a Production environment.

What causes "WinHttpException: The server returned an invalid or unrecognized response" in HttpClient?

PROBLEM:
I am trying to access data from a remote Bugzilla server using Bugzilla's REST API. Whenever I await a response from HttpClient.GetAsync, this exception is thrown.
WHAT I'VE TRIED:
In an effort to understand the exception, I've investigated the following SO questions and GitHub issues:
Meaning of “The server returned an invalid or unrecognized response” in HttpClient
The server returned an invalid or unrecognized response" error when ...
HttpClient fails with "The server returned an invalid or unrecognized ...
CORE CODE:
The purpose of the code below is to get the Bugzilla version of the server at _url_version. For example, if I set _url_version = "https://bugzilla.mozilla.org/rest/version", I get a valid response.
// Get version, dummy test to ensure REST API is working via http requests
public async Task<string> GetVersion()
{
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(_url_version);
string json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Rootobject>(json).version;
}
}
QUESTION:
What is the meaning of this exception? What could be causing the communication break between my application and the remote Bugzilla server?
After doing some digging, I was able to resolve this issue by updating Bugzilla to 5.0.4.
ROOT CAUSE:
By using Curl, I was able to manually examine the headers from the Http response (here). The exception was being caused by noise in the response:
Bugzilla.pm:sysread() is deprecated on :utf8 handles. This will be a fatal error in Perl 5.30 at C:/...
For some reason, this issue with a perl module was being echoed on the server side.
SOLUTION:
According the Bugzilla 5.0.4 release notes, the issue was resolved. I updated my Bugzilla installation and the REST API worked as intended.
Hopefully this is helpful to someone out there!

Connecting to a .NET Core Web API - Unable to connect to remote server

I am trying to make a call from my WPF project to an API that I created in ASP.NET Core. When the call is made to the Web API end point, it is returning an error: Unable to connect to the remote server with the inner error being SocketException: No connection could be made because the target machine actively refused it.
This is all being done on the localhost.
The code that is creating this call is(the second line throws the exception):
string RequestUri = "api/Class/GetEverythingDue";
HttpResponseMessage response = await myClient.GetAsync(RequestUri);
With myClient being an HttpClient that I configured like so:
this.myClient = new HttpClient();
myClient.BaseAddress = new Uri("http://localhost:56030/");
myClient.DefaultRequestHeaders.Accept.Clear();
myClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
I realize there are several questions with similar problems, I just haven't seen any yet that have to do with .NET Core. I just wanted to make sure that the problem wasn't due to using WPF and .NET Core together and it was due to them being incompatible.
Any help is appreciated.
Thanks
The exception usually means either the firewall is stopping you or the remote server is not listening to the port. An error with your code wouldn't throw such an exception unless you closed the connection and then tried to access it.

HttpWebRequest.GetResponse() returning 404 Error

I have some code that calls HttpWebRequest's GetResponse() method to retrieve HTML from a URL and return it to the calling method.
This has been working perfectly fine within my Development and QA environments but now that I have uploaded it to my UAT server, I keep getting the following error:
The remote server returned an error: (404) Not Found.
The main difference between Dev/QA and UAT is that UAT uses SSL/HTTPS based URLs whereas Dev/QA uses HTTP. I introduced the following line of code to help progress me a little futher:
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
where AcceptAllCertifications always returns true but I still get my 404 error.
I that people who previously had this error have been able to resolve the issue by merely ensuring the URI used for the HttpWebRequest doesn't have a slash at the end (see: Simple HttpWebRequest over SSL (https) gives 404 Not Found under C#) but this does not make a difference to me.
I have now tried what was suggested at this post (see: HttpWebResponse returns 404 error) where I render the exception on the page. This bypassed the yellow-warning screen and gives me a bit more informtion, including the URL it is trying to get a response from. However, when I copy and paste the URL into my browser, it works perfectly fine and renders the HTML on the page. I'm quite happy therefore that the correct URL is being used in the GetResponse call.
Has anyone got any ideas as to what may be causing me this grief? As said, it only seems to be a problem on my UAT server where I am using SSL.
Here is my code to assist:
public static string GetHtmlValues()
{
var webConfigParentUrlValue = new Uri(ConfigurationManager.AppSettings["ParentUrl"]);
var destinationUrl = HttpContext.Current.Request.Url.AbsoluteUri;
var path = "DestinationController" + "/" + "DestinationAction" + "?destinationUrl=" + destinationUrl;
var redirect = new Uri(webConfigParentUrlValue, path).AbsoluteUri;
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
var request = (HttpWebRequest)WebRequest.Create(redirect);
//Ensures that if the user has already signed in to the application,
// their authorisation is carried on through to this new request
AttachAuthorisedCookieIfExists(request);
HttpWebResponse result;
try
{
result = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
result = ex.Response as HttpWebResponse;
}
String responseString;
using (Stream stream = result.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
responseString = reader.ReadToEnd();
}
return responseString;
}
More details of the error as it is rendered on the page:
I ran into a similar situation, but with a different error message. My problem turned out to be that my UAT environment was Windows 2008 with .NET 4.5. In this environment the SSL handshake/detecting is performed differently than most web browsers. So I was seeing the URL render without error in a web browser but my application would generate an error. My error message included "The underlying connection was closed: An unexpected error occurred on a send". This might be your issue.
My solution was to force the protocol change. I detect the specific error, then I force a change in the security protocol of my application and try again.
This is the code I use:
catch (Exception ex)
{
if(ex.Message.Contains("The underlying connection was closed: An unexpected error occurred on a send."))
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
// retry the retrieval
}
}
I finally found the solution to my problem...
The first clue to get me on the right track was the wrong physical path being displayed in the 404 error from IIS. It turns out that this incorrect physical path was mapped to another site in my IIS setup. This particular naturally had a binding also; port 443. As you may know, port 443 is the default port for https.
Now looking at my URL that I was trying to pass into the HTTPWebRequest.GetResponse() method, it looked something like this:
https://www.my-web-site.com
Taking this into account, when this application was hosted on IIS within the bounds of SSL, the error was occuring as follows:
Code enters the aforementioned method GetHtmlValues()
The code gets https://www.my-web-site.com from the web.config file
A response is requested from https://www.my-web-site.com
At this point, as no port has been specified and application is now out there on the open internet, it tries to get a response from https://www.my-web-site.com:443
The problem is, my application isn't hosted via IIS on port 443. A different application lives here. Subsequently, as the page can't be found on port 443, a 404 error is produced.
Now for the solution...
Looking in IIS, I found the port that my application sits on. Let's say port 16523.
Whereas previously in my web.config I had my key of ParentUrl decalred with a value of https://www.my-web-site.com, this is to be changed to http://www.my-web-site.com:16523
Note how the https has become http and the port number is specified at the end. Now when the application tries to get the response, it no longer uses the default ssl port as the correct one was specified.

What exception or http status code for when the server is down

I want to monitor a WCF server, and send email notification if the server is down. To accomplish that, I am writing a console app to periodically send dummy request to the server, and check if response is sent back. When the console app received exception the server has issues, including the server being down.
However, the problem is that I received different exception on different status of the server. Below is the exceptions returned from the server when it is on different status. However, all seem belong to server down category. Any idea??:
When IIS is turned off
System.ServiceModel.EndpointNotFoundException,
Message:
There was no endpoint listening at http://localhost/service.svc that could accept the message. This is often caused by an incorrect
address or SOAP action. See InnerException, if present, for more
details.
Inner Exception Message:The remote server returned an error: (404) Not Found
When a Web.config file is deliberately changed to a wrong name:
System.ServiceModel.ServiceActivationException
Link:
http://localhost/service.svc
Message:
The requested service, 'http://localhost/service.svc' could not be activated. See the server's diagnostic trace logs for more
information.
For other unknown reason
System.ServiceModel.ServerTooBusyException
Message:
The HTTP service located at http://localhost/service.svc' is too busy.
Message:
The remote server returned an error: (503) Server Unavailable.
Update 1
The exception does NOT always return http status code.
Update 2
Apart from using WCF proxy to call the service, I have to use WebRequest too, as below:
try
{
WebRequest webRequest = WebRequest.Create(uri);
webRequest.Method = "GET";
HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
}
catch () //what excpetion will tell me server is down??
{
...
}
The actual content of the error shouldn't really be of consequence - unless you're monitoring individual operations on the service (i.e. should a POST with some data to a particular URL return a specific response) - realistically, then, you're just going to be looking at the status code itself; and for that you want to look through all the HTTP Status Codes and see those which look like errors as far as you're concerned.
As a good starting point - you might want to consider nearly all of the 5xx codes; as they are all connected with server errors.
You might also want to consider some of the 4xx codes (although these are usually connected with clients, so be ruthless). In particular:
400 - Bad Request - so long as you can be sure that the server should be able to understand the request
404 - Not Found - if you're sure that the given URL should be present
405 - Method Not Allowed - if you're sure that the given HTTP verb should be supported (e.g. a POST or DELETE)
For some of the narrower 4xx codes, e.g. 413 Request Entity Too Large or 414 Request-URI Too Long; these could conceivably happen after days or months of normal operation due to things like security updates. In which case you're not necessarily identifying that the service is down as such, but you might be anticipating it being unable to perform it's intended function.
Any HTTP status result code in the 400 or 500 series is a problem that will prevent you're request from processing. All of these errors derive from System.ServiceModel.CommunicationException so check for that.

Categories

Resources