I'm working on a web application that runs with ASP.Net 3.5
Somewhere in the application, I'm making calls to an external system. This call consists on downloading a string from a specific url :
string targetUrl = BuildMyUrl();
WebClient wc = new WebClient();
string data = wc.DownloadString(targetUrl);
This code works quite well with a acceptable response time (under 500ms).
However, in specific cases this response time is over 15 seconds. I can reproduce the behavior, and I can clearly see the long time is on the DownloadString call.
I don't understand why this occurs in my scenario.
You will say : "Hey, it's the target system that is slow". But I was not able able to reproduce the behavior outside my application (I've build a small console application that isolate the faulting code. Never get any issue).
I don't know where to look now to understand the issue. What can cause a simple download data to be be lengthy ?
FYI: the target system is an authentication service. The target url is of kind :
httpS://mysystem/validate?ticket=XXXYYY
Maybe the https protocol is the issue.
Does using WebClient class under IIS can alter the behavior of the WebClient ?
[Edit] I've tried :
To explicitly set the Proxy property of the WebClient object to null
I've replaced the DownloadData call by this code :
var req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(targetUrl));
using (var response = (HttpWebResponse)req.GetResponse())
{
using (var sr = new StreamReader(response.GetResponseStream()))
{
data= sr.ReadToEnd();
}
}
None of this test were successful.
Try to use Fiddler or some integrated network analyzer inside Chrome/FF browsers to see the HTTPS requests/responses and their headers.
The latency was due to a certificate validation timeout. One of the issuer in the chain was not correctly deployed in the client server.
Related
I'm makin an API with net core 2.1 and run into a issue where I CAN gen a correct response in my local machine (even running the published files) BUT gen stuck when i upload and run the app in a aws ec2 windows server 2012.
I've tried using the IHttpClientFactory, adding the httpclient at services collection, making a service whith the AddHttpClient and running the release profile in my pc and with every method it runs fine in my pc but hangs in aws ec2 windows server 2012.
I'm running the app in aws ec2 with $netcore ./application.dll for now.
my pc has netcore 2.2.300 and aws 2.2.400
Here is the part of the code I use in my controller (also try with making a service):
WebCuitRequest req = new WebCuitRequest {cuit = "cuit", token = "Yt25zBH" };
string json = JsonConvert.SerializeObject(req);
string baseUrl = "url.com/getthis";
StringContent queryString = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage res = await _client.PostAsync(baseUrl, queryString);
//------i dont get here (no error, no response)
HttpContent content = res.Content;
string data = await content.ReadAsStringAsync();
return data;
I expect an error or response but none is returned (i have a try/catch and some Console.write that never get reached).
Update 1 (solution):
Moving the API I was trying to reach to a hosting without cloudfare solved the problem. It seems that cloudfare was blocking the aws instance (but no my pc) and for some reason I didn't get a response or error. I must clarify that I have access to the target API and the posibility to move it, I don't know what can be done if you can't do changes in that env.
Tanks to Robert Perry who get me to evaluate another part on the situation.
This is most likely caused by Azures' default security settings. I believe it locks out calls to external IP addresses by default - its worth checking this article and matching it to how your Azure is configured: https://learn.microsoft.com/en-us/azure/storage/common/storage-network-security
Moving the API I was trying to reach to a hosting without cloudfare solved the problem.
It seems that cloudfare was blocking the aws instance (but no my pc) and for some reason I didn't get a response or error.
I must clarify that I have access to the target API and the posibility to move it, I don't know what can be done if you can't do changes in that env.
Edit: after talking it over with a couple IT guys, I've realized it's only the POLL requests that are having issues. I'm fetching the images via GET requests that go through quickly and as expected, whether or not the POLL messages are having issues.
I'm working on a client to interface with an IP camera in C#.
It's all working dandy except that I can get really poor http request performance when I'm not using Fiddler (a web traffic inspection proxy).
I'm using an httpclient to send my requests, this is my code that actually initiates the poll request:
public async Task<bool> SetPoll(int whichpreset)
{
string action = "set";
string resource = presetnames[whichpreset];
string value = presetvalues[whichpreset];
int requestlen = 24 + action.Length + resource.Length + value.Length;
var request = new HttpRequestMessage
{
RequestUri = new Uri("http://" + ipadd + "/res.php"),
Method = HttpMethod.Post,
Content = new FormUrlEncodedContent(new[]{
new KeyValuePair<string,string>("action",action),
new KeyValuePair<string,string>("resource",resource),
new KeyValuePair<string,string>("value",value)
}),
Version = new System.Version("1.1"),
};
HttpResponseMessage mess = await client.SendAsync(request);
if (mess.IsSuccessStatusCode)
{
return true;
}
else
{
return false;
}
}
When Fiddler is up, all my http requests go through quickly, and without a hitch (I'm making about 20 post requests upon connecting). Without it, they only go through as expected ~1/5 of the time, and the rest of the time they're never completed, which is a big issue. Additionally, the initial connection request often takes 1+ minutes when not using Fiddler, and consistently only takes a few seconds when I am, so it doesn't seem to be a timing issue of sending requests too soon after connecting.
This leads me to think that the request, as written, is fairly poorly behaved, and perhaps Fiddler's requests behave better. I'm a newbie to HTTP, so I'm not sure exactly why this would be. My questions:
does Fiddler modify HTTP requests (E.G. different headers, etc.)
as they are sent to the server?
even if it doesn't modify the requests, are Fiddler's requests in
some way better behaved than I'd be getting out of .net 4.0 in C# in
VS2013?
is there a way to improve the behavior of my requests to emulate
whatever Fiddler is doing? Ideally while still working within the
stock HTTP namespace, but I'm open to using others if necessary.
I'll happily furnish more code if helpful (though tomorrow).
Inserting
await Task.Delay(50);
between all requests fixed the problem (I haven't yet tested at different delays). Because Fiddler smoothed the problem out, I suspect it's an issue the camera has with requests sent in too quick of a succession, and fiddler sent them at a more tolerable rate. Because it's an async await, there is no noticeable performance impact, other than it taking a little while to get through all ~20 (30 now) requests through on startup, which is not an issue for my app.
Fiddler installs itself as a system proxy. It is possible that the Fiddler process has better access to the network than your application's process.
Fiddler might be configured to bypass your normal system proxy (check the gateway tab under options) and perhaps the normal system proxy has issues.
Fiddler might be running as a different user with a different network profile, e.g. could be using a different user cert store or different proxy settings such as exclusion list.
Fiddler might be configured to override your hosts file and your hosts file may contain errors.
Your machine might be timing out trying to reach the servers necessary to check for certificate revocation. Fiddler has CRL checking disabled by default (check the HTTPS tab).
Fiddler has a ton of options and the above are just some guesses.
My recommendation would be to check and/or toggle the above options to see if any of them apply. If you can't get anywhere, you may have to forget Fiddler exists and troubleshoot your network problems independently, e.g. by using NSLOOKUP, PING, TRACERT, and possibly TELNET to isolate the problem.
There is nothing in your code sample that suggests a code flaw that could cause intermittent network failures of the kind you are describing. In fact it is hard to imagine any code flaw that would cause that sort of behavior.
Summary:
I am using Hangfire to handle running background jobs at set intervals, like checking for expired Widgets nightly. I want to know the best way to hit an ASP.NET Web Api 2 endpoint (Likely just GET and POST) from a job that is running.
Versions of stuff (if this matters)
.NET 4.5 MVC 5
Web Api 2(.1?)
Hosting sites Windows azure
8GB of RAM see footnote (1)
local dev using IIS express (or whatever the builtin one is in VS2013)
My specific questions
Is this implementation the proper way to open/close a connection to my api from something like a background task?
In the code below, how can I dynamically get the client.BaseAddress string (http://whatever.xxx)? It would be incredibly handy to be able to do some like what I have in the second psuedo-code snippet.
Here is the code I got from this blog post
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:43736/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
HttpResponseMessage response = await client.GetAsync("api/do/someshiz/");
if (!response.IsSuccessStatusCode)
{
//todo: stuff
}
}
This is pretty clean already I suppose but I am woefully inexperienced with using the HttpClient class and most of my api interactions are from javascript.
What I want to do for getting the HttpClient.BaseAddress string
if(IAmRunningThisOnMyLocalMachine) {
baseAddress = "http://localhost:1337/"
} else {
//I Already have a way to determine if I am on the staging server or live site
if(IsStagingServer){
// staging server base address
baseAddress = "http://staging.whatever.com/"
} else {
// live base address
baseAddress = "http://whatever.com/"
}
}
For the root else branch it is less of a big deal, those strings are more or less constant. When I am running locally though I want it to work regardless of if I am localhost:AnyPort or any other variations of IIS Express.
1: Just kidding about the RAM, just wanted to see if I could make the read whisper 'wtf' out loud. Please advise if successful
I am having a lot of trouble using Webrequests in MonoDroid and getting timeouts at random. My code works fine then sometimes all requests just timeout and don't work.
I have verified the webservices used in my requests are not the problem.
Here is an example of some code that I may use to request some data from a webservice using MonoDroid:
bool bolOk = false;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create ("http://www.website.com/service/");
request.Timeout = 20000;
request.Credentials = gv_objCredentials;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse ()) {
bolOk = response.StatusCode == HttpStatusCode.OK;
}
As you can see it is basic stuff. I use code like the above always on another thread to the UI using ThreadPool.QueueUserWorkItem or TaskFactory.
What I have noticed is that if the requests start timing out from my app and I plug it in to my computer then debug the app from MonoDevelop the requests work without timing out. I am not sure if this means anything. This is similar to testing the webservices from my computer using a browser on the same network as the phone. The webservices always work without any issues.
What is the best way to make Webrequests from MonoDroid?
How can I ensure my requests are always successful and won't timeout if the webservice is operating correctly?
I had the Issue on Xamarin 4.2.6 and 4.2.8.
Thanks to Xamarin support, they identified the issue and suggested I targeted my build to armeabi-v7a rather than armeabi in my project properties (some multi-core processor issue described here)
Depending on whether you plan to support multi-core processors or not, you should check our this post and may need to manually edit your .csproj file.
There's a new version of Mono for Android (4.2.5) that fixes a number of bugs with the WebRequest and webRequestStream. You can check the release notes here: http://docs.xamarin.com/android/Releases/Mono_For_Android_4/Mono_for_Android_4.2.5
I suggest downloading the latest bits and check if it works. If not, please file a bug and they will surely fix it in the next version of the product.
I am using this code to download file from server and parse data from JSON notation:
WebClient wcl = new WebClient();
Uri url = new Uri(tickurl);
string srlz = wcl.DownloadString(url);
var dict = (new JavaScriptSerializer()).Deserialize<Dictionary<string, dynamic>>(srlz);
When I use it with http://deepbit.net/api/ + my token (URI returns JSON data) it works well.
But with https://mtgox.com/code/data/ticker.php it stucks on 3rd line of the function(data downloading).
What am i doing wrong? Both URLs return same JSON formatted data.
[add] it's not issue with https, this code works well enough with other https services. i am wondering if this could be a problem with SSL cert.
SOLVED: turned off SSL certificate validation. thanks
I suspect it's failing due to a security problem. When I fetch with wget, I get:
ERROR: certificate common name www.mtgox.com' doesn't match requested host namemtgox.com'
It's fine when I fetch with wget using the --no-check-certificate flag.
I don't know whether you can persuade WebClient not to check certificates... but a better option would obviously be to get the certificate fixed.
Alternatively, try this URL instead: https://www.mtgox.com/code/data/ticker.php - note the www at the front. That fetches in wget without any issues.
The Url: https://mtgox.com/code/data/ticker.php doesn't even open up in browser. It starts downloading the 'ticker.php' file. Your server is misconfigured. The code is fine. Most probably the server is not properly configured to process .php files as scripts.
it is a certificate error like Jon Skeet said.
Have a look here to find a easy solution
WebClient + HTTPS Issues
you shouldn't use this for all request, only for debugging