WebRequest.GetResponse is not returning anything - c#

I am stuck with this, I am calling a simple report server URL which returns report's PDF, but strangely the WebRequest.GetResponse method doesn't return anything, when I say this, I mean the code just stop executing at that point, no exception, no error, no status code, no event viewer log on server, nothing!! And so I am not able to debug it
This is my code
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.PreAuthenticate = true;
req.UseDefaultCredentials = true;
req.Credentials = CredentialCache.DefaultNetworkCredentials;
req.ImpersonationLevel = TokenImpersonationLevel.Impersonation;
req.Timeout = int.MaxValue;
Log.Write("Log before");
var response = req.GetResponse();
Log.Write("Log after");
It just prints Log before log and then nothing is printed after that.
This code works perfectly fine when I run through visual studio and stops working when it is deployed in dev and test servers!
I am just expecting it to atleast through the exception or return unauthorized or any other status code, then I will be able to debug the issue.
Any suggestions what I can try to debug it?

Have you tried leaving it for 24 days 20 hours 31 minutes and 24 seconds? In other words, have you left it for as long as you have set the timeout to?
The server is not returning a response and the code is waiting int.MaxValue milliseconds to tell you that. The most likely cause of this is that there is a piece of networking infrastructure between your client and server that is stopping the request. This could be a firewall or proxy. It may also be being caused by the server not liking the request and refusing to respond.
Things I would try:
Try accessing the URL though a web browser on the machine that the code is failing on.
Set the timeout to something sensible like one minute and run the request to timeout.
Try pinging the remote server from the client machine.
Use a product like Fiddler to check what is actually being sent and received.
Have a chat with your network provider to see if they can help.
Check the server logs to see if the server has erred.
Change the first log to Log.Write("Log before: " + url); to check what is actually being requested.

Related

Debugging a long running Webservice Call

I'm using C# to connect to a Webservice to grab data. However, I'm currently having problems getting the code to run on a remote server; when I say problems, I mean its running, but the connection speed between client and server is ridiculously slow (through no fault of mine - the client is providing a slow resultset via a webservice, and they have all timeouts turned off their side in order to do so.)
if ((endpointConfiguration == EndpointConfiguration.SFFService))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
result.OpenTimeout = TimeSpan.MaxValue;
result.CloseTimeout = TimeSpan.MaxValue;
result.SendTimeout = TimeSpan.MaxValue;
return result;
}
So. Not a great start. Open Close and Send all set to maximum.
Anyway, I've matched their long timeouts my side, and a few of the smaller webservice requests finish and succeed ok on the server. The biggest, slowest one however just hangs indefinitely, probably because I've told it to never timeout.
However, I'm pretty sure there's some other problem happening, as I left it overnight and it just sat there. Locally, on my development machine, although slow, it works.
My question is, has anyone any idea on additional things to check about the environment that could potentially be in play here? I thought perhaps firewall, but given that the small requests succeed (and connect) it is very difficult to debug the slow requests as I've no idea how long to wait until accepting that the program isn't going to do anything.
FWIW I've tried connecting via a browser, and again, the browser just sits there waiting for the request to finish which it never does (most likely due to the timeout being turned off on the server). If there was any way to see even how much of the request was left to finish (like a percentage download) that may help give me some guidance as to if the code is doing anything other than waiting.
There's no way to get a progress of the remote call even when you are attached to the remote process. Try using a local Visual Studio on the server machine (preferably on a non-production VM) and attach to the local process rather than using the Remote Debugger.
I am not sure exactly what the question is but the first step I'd take while debugging a slow application would be to test a local connection (local client and local server) to eliminate the network from the equation. If that works well, try hosting the server on a different place (public cloud maybe?) and try again there, if it works well then there's definitely something en-route or on that server.
If you're interested in tracking how long web service calls take you could track it by placing the start time into the HttpContext.Current.Items or OperationContext.Current.Items on BeginRequest/EndRequest in Global.asax or in a MessageInspector if you use WCF (you can send the datetime between the two methods by returning it into the Before method and read it from the corelationState parameter in the After method).

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.

C# HttpWebRequest.GetResponse() hangs when requesting a method of Azure web role

I'm writing code to send a request to my web service in windows azure, and it turned out I cannot get response until timeout. What's confusing is that i'm sure everything inside my service has been done, and yet the response did not come back.
My service code looks like this:
public virtual JsonResult ServiceMethod()
{
// 1. do the work
// 2. write something to database
return Json(result, JsonRequestBehavior.AllowGet);
}
And my client code looks like this:
HttpWebRequest webRequest = WebRequest.Create(new Uri(httpAddress)) as HttpWebRequest;
webRequest.Timeout = 1000 * 1000;
webRequest.ServicePoint.ConnectionLeaseTimeout = 40 * 60 * 1000;
webRequest.ServicePoint.MaxIdleTime = 40 * 60 * 1000;
webRequest.ServicePoint.SetTcpKeepAlive(true, 50 * 1000, 1000);
webRequest.Method = "GET";
using (HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)
{
// handle the response
}
Now I'm pretty sure my code in my service has completed because i tried to write something to database and that happened. I also checked the iis log on the virtual machine where the service is hosted and it showed http 200 is returned. But the call GetResponse() in my client code hanged until the 1000 seconds timeout is reached.
Update
There is a parameter to my web API which will affect how long the method runs.(I didn't show it in the above code for simplicity). If the service method runs for sufficiently long time (like 6 or 7 minutes), then the hanging problem will happen. Otherwise, the web response can successfully return. So i guess there might be some problem within the timeout setting. But there are several timeout properties in the HttpWebRequest and its base classes, i don't know what combination of them can result in or solve this problem.
Any ideas of what can the problem be?
Thanks a lot.
From your code, and since you're returning JsonResult from your action, it seems that you have a RESTful architecture. One of the ways to debug RESTful architectures is to use browser, specifically in your case where HTTP method is GET.
You can simply copy/paste your URL in the address bar of a browser to see if you get any response. If you see the result, then your client code is the problem, otherwise, the problem is in the server side (azure server).
To monitor HTTP traffic, a good utility is Fiddler.
Run your project locally in the Windows Azure emulator. Then, check the output of the compute emulator. It should show unhandled exceptions there.
It seems that the call to your external service fails, and the exception is not handled properly. We've had a similar case before, and it would even cause the IIS worker process to crash.

responding policy-file-request of flash from c#

i have developed a server application with c# and a client application with flash action script 3.0. Flash socket asking for a policy file when called from a browser with a message
<policy-file-request/>
everything is normal so far. My server is waiting for this message and sending to client a policy file string which is like this:
public const String POLICY_FILE = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" +
"<cross-domain-policy>" +
"<allow-access-from domain=\"*\" to-ports=\"*\" />" +
"</cross-domain-policy>\u0000";
this string is being sent this way:
if (message.Contains("policy-file-request"))
{
client.Send(Encoding.ASCII.GetBytes(Statics.POLICY_FILE));
return;
}
I'm pretty sure that this was working but i really don't know what happened and started not working. When flash client receives this message from server, connection was succesfull and everything was going how it had to go. But now the flash client waits 20 seconds (timeout of flash socket) and throws security exception
[SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]
I'm stuck and can't move forward. I'm listening to port 963, server machine fully qualified name is "mypc.domain.local" which can be accessible across my network. there is also an IIS running on this machine and the flash application is hosted here.
http://mypc.domain.local:90/page.html
this is the way, i call my flash application and
mypc.domain.local:963
is the address of server running. i am also working on this machine. i tried calling the page http://localhost:90/page.html or http://127.0.0.1:90/page.html and also tried the connection to server as localhost:963 or 127.0.0.1:963. same result on every combination.
What is wrong here? what could have been changed causing my working code broke down?
Thanks.
It's hard to tell without more code, but based on what you've shown, it appears that when that request comes in, you respond with the contents of the policy file, which isn't an actual valid HTTP response. My guess for the 20 second timeout would be that it's still waiting for the HTTP headers.
If possible, try to use the HTTP classes already in the BCL instead of doing http 'manually', but if you have to do the socket stuff yourself, then use something like Fiddler during debugging since it's great for identifying violations of the HTTP protocol.

Using .NET's HttpWebRequest to download a multitude of files in a row

I have an application that needs to download several files in a row in succession (sometimes a few thousand). However, what ends up happening when several files need to be downloaded is I get an exception with an inner exception of type SocketException and the error code 10048 (WSAEADDRINUSE). I did some digging and basically it's because the server has run out of sockets (and they are all waiting for 240s or so before they become available again) - not coincidentally it starts happening around the 1024 file range. I would expect that the HttpWebRequest/ServicePointManager would be reusing my connection, but apparently it is not (and the files are https, so that may be part of it). I never saw this problem in the C++ code that this was ported from (but that doesn't mean it didn't ever happen - I'd be surprised if it was, though).
I am properly closing the WebRequest object and the HttpWebRequest object has KeepAlive set to true by default. Next my intent is to fiddle around with ServicePointManager.SetTcpKeepAlive(). However, I can't see how more people haven't run into this problem.
Has anyone else run into the problem, and if so, what did you do to get around it? Currently I have a retry scheme that detects this error and waits it out, but that doesn't seem like the right thing to do.
Here's some basic code to verify what I'm doing (just in case I'm missing closing something):
WebRequest webRequest = WebRequest.Create(uri);
webRequest.Method = "GET";
webRequest.Credentials = new NetworkCredential(username, password);
WebResponse webResponse = webRequest.GetResponse();
try
{
using(Stream stream = webResponse.GetResponseStream())
{
// read the stream
}
}
finally
{
webResponse.Close()
}
What kind of application is this? You mentioned that the server is running out of ports, but then you mentioned HttpWebRequest. Are you running this code in a webservice or ASP.NET page, which is trying to then download multiple files for the same incoming request from the client?
What kind of authentication is the page using? If it is using NTLM authentication, then the connections cannot be shared if the credentials being used are different for each request.
What I would suggest is to group your request per credential. So, for eg, all requests using username "John" would be grouped. You can specify the "ConnectionGroupName" property on the service point, so the system will try to reuse connections for the same credential and server.
If that also doesnt work, you will need to do one or more of the following:
1) Throttle your requests.
2) Increase the wildcard port range.
3) Use the BindIPConnectionCallback on ServicePoint to make it bind to a non-wildcard port (i.e a port in the range 1024-16384)
More digging seems to point to it possibly being due to authentication and the UnsafeAuthenticatedConnectionSharing property might alleviate this. However, I'm not sure that's the best thing, either.

Categories

Resources