HttpWebResponse.ReadTimeout - Timeouts not supported? - c#

We have an issue where on a single instance of our product we receive an InvalidOperationException exception when we attempt to set the ReadTimeout property of an System.Net.HttpWebResponse object.
This issue is occurring only on a single instance, where we have many multiple live sites without this problem. We've tried to recreate the issue locally, to no avail.
The following code illustrates the issue.
Any ideas are greatly welcome.
Thanks
private static XmlReader GenerateReaderFromResponse(HttpWebResponse response, HttpWebRequest request)
{
Stream responseStream = response.GetResponseStream();
responseStream.ReadTimeout = request.Timeout; //This is where the exception is generated - System.InvalidOperationException: Timeouts are not supported on this stream.
using (StreamReader responseReader = new StreamReader(responseStream, System.Text.Encoding.UTF8))
{
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.ProhibitDtd = false;
string responseContent = responseReader.ReadToEnd();
return XmlReader.Create(new StringReader(responseContent), readerSettings);
}
}

What you need is the HttpWebRequest.ReadWriteTimeout property.
It specifies the number of milliseconds before the reading (or writing) operation on the response Stream times out, throwing a WebException with Status set to WebExceptionStatus.RequestCanceled.
From the msdn documentation:
The ReadWriteTimeout property is used when writing to the stream
returned by the GetRequestStream method or reading from the stream
returned by the GetResponseStream method.
Specifically, the ReadWriteTimeout property controls the time-out for
the Read method, which is used to read the stream returned by the
GetResponseStream method, and for the Write method, which is used to
write to the stream returned by the GetRequestStream method.
To specify the amount of time to wait for the request to complete, use
the Timeout property.

First, make sure that responseStream and request are not null.
Them, you should make sure that the server did respond to your request after trying to read the response from it.
If you can, please also provide the code that sends the request.

Related

Either ContentLength must be set to a non-negative number, or SendChunked set to true in order to perform the write operation

Using HttpWebRequest, I used the following code to request a soap and get a stream:
XmlDocument soapEnvelopeXml = new XmlDocument();
HttpWebRequest webRequest = ...
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
While this is the error message:
Either ContentLength must be set to a non-negative number, or SendChunked set to true in order to perform the write operation when AllowWriteStreamBuffering is disabled.
As the above message says, I can't write to the stream because if I call the save soapEvelopeXml the application ends.
To resolve the error, simply enable a parameter within the HttpWebRequest object.
webRequest.AllowWriteStreamBuffering = true;
The parameter is part of the object properties and citing from the documentation on learn.microsoft.com
AllowWriteStreamBuffering : Gets or sets a value that indicates whether to buffer the data sent to the Internet resource

Proper way to read and write web api response stream

I'm having some trouble with finding the right incantation that will allow me to write to a response stream and then later read the contents in a test. Currently I have this
var res = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
var ms = new MemoryStream();
res.Content = new StreamContent(ms);
using (var sw = new StreamWriter(ms, System.Text.Encoding.UTF8))
using (var csv = new CsvHelper.CsvWriter(sw))
csv.WriteRecords(allData.ToList());
return res;
In my test I'm trying to read this response
var controller = appContainer().Resolve<MyController>();
var res = (await controller.Get()) as HttpResponseMessage;
res.ShouldNotEqual(null);
var csv = await res.Content.ReadAsStringAsync();
the last line generates an error
Error while copying content to a stream.
----> System.ObjectDisposedException : Cannot access a closed Stream.
So there's a couple things here
Why is this error happening and how can I prevent it properly in the test?
The use of MemoryStream doesn't sit right with me, shouldn't I be able to write directly to the content's stream? Isn't MemoryStream potentially hugely increasing my memory usage?
Just put this out there, though it's not perfect... Using PushStreamContent does a lot of the job but it comes with its own headaches - namely that any exceptions that your anonymous method may produce will get swallowed and be difficult to track down without a full repro of the problem. When the bomb goes off is well passed the point of the pipeline where web api unhandled exception handlers would come into effect, and the xmlhttprequest doesn't seem to recognize the closure.
E.g. something like
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new PushStreamContent((stream, content, context) =>
{
// write your output here
});
return response;
will get you what you want, provided that internal method never slips up or goes wrong in any way.
PushStreamContent flushes your http headers immediately before the anonymous method is called, so you're chunked and no way to reel it back in later.
You can add a try/catch in your anonymous method to leave yourself a note if something goes wrong, but in my experience XmlHttpRequest doesn't recognize when the remote server forcibly closes the request so it keeps on waiting. Only started to figure out what was going on when I put Fiddler in there, and Fiddler squawked.

C# GetRequestStream() outlook add-in "The operation has timed out"

Good day.
I really need help on this issue. I have tried every possible option here.
I use a REST API in an Outlook add-in using C#. The code links outlook items to CRM records, one way. The add-in works 100% fine but after a couple of calls outs i keep on getting the error "The operation has timed out".
When I use the Google Chrome App "Advanced REST Client" I can post the same request 50 times after each other with no time out error.
From within the add-in I use POST, GET and PATCH HttpWebRequest and I get the error for all of them. The error happens at the code line System.IO.Stream os = req.GetRequestStream();
Below is the method:
public static string HttpPatch(string URI, string Parameters)
{
var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(URI);
if (GlobalSettings.useproxy.Equals("true"))
{
req.Proxy = WebRequest.DefaultWebProxy;
req.Credentials = new NetworkCredential(GlobalSettings.proxyusername, GlobalSettings.proxypassword, GlobalSettings.proxydomain);
req.Proxy.Credentials = new NetworkCredential(GlobalSettings.proxyusername, GlobalSettings.proxypassword, GlobalSettings.proxydomain);
}
req.Headers.Add("Authorization: OAuth " + GlobalSettings.token.access_token);
req.ContentType = "application/json";
req.Method = "PATCH";
byte[] data = System.Text.Encoding.Unicode.GetBytes(Parameters);
req.ContentLength = data.Length;
using (System.IO.Stream os = req.GetRequestStream())
{
os.Write(data, 0, data.Length);
os.Close();
}
WebResponse resp;
try
{
resp = req.GetResponse();
}
catch (WebException ex)
{
if (ex.Message.Contains("401"))
{
}
}
}
I suspect the problem is that you're not disposing of the WebResponse. That means the connection pool thinks that the connection is still in use, and will wait for the response to be disposed before reusing it for another request. The connection is needed in order to get a request stream, and it won't become available unless the finalizer happens to kick in at a useful time, hence the timeout.
Simply change your code using the response to use a using statement - or in your case, potentially something a little more complicated using a finally block as you're assigning it within a try block. (We can't really see how you're using the response, which makes it hard to give sample code around that. But fundamentally, you need to dispose it.)

Question about HttpWebRequest class in .net

I would like to know two things about the following code:
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";
myWriter = new StreamWriter(objRequest.GetRequestStream());
myWriter.Write(strPost);
Here are my two questions:
- What is exactly a stream?
- The line myWriter.Write sends an Http Packet with the post information or to do that i have to use a method of HttpWebRequest class?
As already stated a Stream is the usual .NET equivalent of a buffer. It's also almost always used when doing any sort of IO, be it files, pipes, network. Usually to work with a stream you use either StreamReader or StreamWriter.
Your method should be sending a packet correctly. To read a response you would do a similar operation with GetResponseStream.
A stream in .NET can be regarded as kind of a buffer.
It is used in file/http/memory IO
The stream in this case is a buffer which will be sent over network. This buffer is sent when you use GetResponse function
http://msdn.microsoft.com/fr-fr/library/system.net.webresponse.getresponsestream%28VS.80%29.aspx

System.Net.WebException: The operation has timed out

I have a big problem: I need to send 200 objects at once and avoid timeouts.
while (true)
{
NameValueCollection data = new NameValueCollection();
data.Add("mode", nat);
using (var client = new WebClient())
{
byte[] response = client.UploadValues(serverA, data);
responseData = Encoding.ASCII.GetString(response);
string[] split = Javab.Split(new[] { '!' }, StringSplitOptions.RemoveEmptyEntries);
string command = split[0];
string server = split[1];
string requestCountStr = split[2];
switch (command)
{
case "check":
int requestCount = Convert.ToInt32(requestCountStr);
for (int i = 0; i < requestCount; i++)
{
Uri myUri = new Uri(server);
WebRequest request = WebRequest.Create(myUri);
request.Timeout = 200000;
WebResponse myWebResponse = request.GetResponse();
}
break;
}
}
}
This produces the error:
Unhandled Exception: System.Net.WebException: The operation has timed out
at System.Net.HttpWebRequest.GetResponse()
at vir_fu.Program.Main(String[] args)
The requestCount loop works fine outside my base code but when I add it to my project I get this error. I have tried setting request.Timeout = 200; but it didn't help.
It means what it says. The operation took too long to complete.
BTW, look at WebRequest.Timeout and you'll see that you've set your timeout for 1/5 second.
Close/dispose your WebResponse object.
I'm not sure about your first code sample where you use WebClient.UploadValues, it's not really enough to go on, could you paste more of your surrounding code? Regarding your WebRequest code, there are two things at play here:
You're only requesting the headers of the response**, you never read the body of the response by opening and reading (to its end) the ResponseStream. Because of this, the WebRequest client helpfully leaves the connection open, expecting you to request the body at any moment. Until you either read the response body to completion (which will automatically close the stream for you), clean up and close the stream (or the WebRequest instance) or wait for the GC to do its thing, your connection will remain open.
You have a default maximum amount of active connections to the same host of 2. This means you use up your first two connections and then never dispose of them so your client isn't given the chance to complete the next request before it reaches its timeout (which is milliseconds, btw, so you've set it to 0.2 seconds - the default should be fine).
If you don't want the body of the response (or you've just uploaded or POSTed something and aren't expecting a response), simply close the stream, or the client, which will close the stream for you.
The easiest way to fix this is to make sure you use using blocks on disposable objects:
for (int i = 0; i < ops1; i++)
{
Uri myUri = new Uri(site);
WebRequest myWebRequest = WebRequest.Create(myUri);
//myWebRequest.Timeout = 200;
using (WebResponse myWebResponse = myWebRequest.GetResponse())
{
// Do what you want with myWebResponse.Headers.
} // Your response will be disposed of here
}
Another solution is to allow 200 concurrent connections to the same host. However, unless you're planning to multi-thread this operation so you'd need multiple, concurrent connections, this won't really help you:
ServicePointManager.DefaultConnectionLimit = 200;
When you're getting timeouts within code, the best thing to do is try to recreate that timeout outside of your code. If you can't, the problem probably lies with your code. I usually use cURL for that, or just a web browser if it's a simple GET request.
** In reality, you're actually requesting the first chunk of data from the response, which contains the HTTP headers, and also the start of the body. This is why it's possible to read HTTP header info (such as Content-Encoding, Set-Cookie etc) before reading from the output stream. As you read the stream, further data is retrieved from the server. WebRequest's connection to the server is kept open until you reach the end of this stream (effectively closing it as it's not seekable), manually close it yourself or it is disposed of. There's more about this here.
proxy issue can cause this. IIS webconfig put this in
<defaultProxy useDefaultCredentials="true" enabled="true">
<proxy usesystemdefault="True" />
</defaultProxy>
I remember I had the same problem a while back using WCF due the quantity of the data I was passing. I remember I changed timeouts everywhere but the problem persisted. What I finally did was open the connection as stream request, I needed to change the client and the server side, but it work that way. Since it was a stream connection, the server kept reading until the stream ended.
I encountered the same error than adding
Task.Delay(2000);
in each request solved the problem

Categories

Resources