I've written some code which does a post to a remote webservice. I've tried using both HttpClient.PostAync as well as HttpClient.SendAsync, where with the former I just provide everything up front, and with the later I build an HttpRequestMessage with the appropriate values. In my testing today I'm getting some type of exception here. The same exception with both implementations. Presumably a timeout, or other error on the remote side / transmission. When I get this exception, it comes with the generic message of 'A task was cancelled'.
The code looks something like this:
using (MultipartFormDataContent formData = new MultipartFormDataContent())
{
//formData.Add(clientIDContent, "client_id");
//formData.Add(clientSecretContent, "client_secret");
formData.Add(quoteIDContent, "CPQuoteID");
formData.Add(poNumContent, "PONumber");
formData.Add(dealerNumContent, "DealerNumber");
formData.Add(orderUserContent, "OrderingUser");
formData.Add(fileContent, "order-file");
try
{
var response = await client.PostAsync(actionURL, formData);
int I = 0;
}
catch (Exception ex)
{
int x = 0;
}
}
the exception I get back is of type TaskCanceledException. The inner exception also carries no meaningful information. There must be a way to get better information back from this. It's frustrating to debug issues when our logs contain only generic messages like this. How do I get this info?
Just a bit more info. I'm operating under the assumption here that the HTTP client does this operation with a Task. At some point the task times out. I don't know if this is because the HTTP timeout is greater than the task timeout in some way, or if the HttpClient object catches the timeout exception, consumes it, then cancels the task throwing the cancellation exception. Either way, it would seem that meaningful information about the underlying issue is lost. Info I'd like to log.
Related
Right now, I'm not talking about ArgumentNullException or InvalidOperationException, but more or less only about HttpRequestException.
var responseAsync = httpClient.SendAsync(something);
try
{
var response = await responseAsync;
}
catch(Exception)
{
}
Will this code ever throw any exceptions, or can we safely assume that all the possible exceptions can only happen during the await?
"but more or less only about HttpRequestException"
MSDN:
The doco makes it quite clear:
HttpRequestException
The request failed due to an underlying issue such as network connectivity, DNS failure, server certificate validation or timeout.
So the answer would be "yes" if say your cat pulled out the network lead for example.
Will this code ever throw any exceptions,
Yes.
or can we safely assume that all the possible exceptions can only happen during the await?
It can occur on the following line too because by the time SendAsync returns (not to be confused with when the Task is complete), the Task has already been created and there is a tiny chance of it throwing before you get to the next line.
var responseAsync = httpClient.SendAsync(something);
EDIT: (from my comment below)
Also, for all we know, SendAsync might perform some "initial check" prior to the Task being created. In which case you'll need a try/catch on the above.
Im using a Request System called xNet and it seems ObjectDisposedExceptions are occuring which on-occurence causes a HUGE cpu spike, sometimes continuously keeping CPU at 99-100% causing freezes and lag.
The script mentioned is the following:
https://github.com/PR4GM4/xNet-Ameliorated
An example code is:
using (HttpRequest httpRequest = new HttpRequest()) {
string url = "https://httpbin.org";
string[] proxysplit = proxy.Split(':');
httpRequest.Proxy = new InternalProxyClient(ProxyType.HTTP, proxysplit[0], int.Parse(proxysplit[1]), null, null);
httpRequest.UserAgent = Http.ChromeUserAgent();
httpRequest.KeepAlive = true;
httpRequest.ConnectTimeout = 15000;
httpRequest.AllowAutoRedirect = true;
HttpResponse hr = httpRequest.Start(HttpMethod.GET, new Uri(url, UriKind.Absolute), new StringContent(""));
if (hr == null) return "2";
string sr = hr.ToString();
if (sr == null) return "2";
}
(If a list of half/dead proxies are needed, I can provide it, just im not sure if linking to them is allowed or not.)
Big note here, it seems to only ever occur whenever theres some kind of other exception like failing to connect to the proxy, or a general bad response, so good connection proxies and/or no proxy at all never has this issue (unless again a general failed error).
If you loop this code, and give it a dead proxy (And to speed things up, multi-thread it to around 5 a time) it will eventually cause an exception like bad response or a timeout and eventually an objectdisposedexception.
I tried debugging in Visual Studio but it gives me almost no information, Historical Debugging gives no information just "Source not found".
Call Stack for the First Exception Thrown of the ObjectDisposedException in the screenshot above.
Seems to be related to line 1430 in ~Http/HttpRequest.cs or line 217 in ~Proxy/ProxyClient.cs as it's the only line I know to exist thats to do with EndConnect socket and also coincidentally can produce ObjectDisposedException. Just not sure how to properly handle the exception here without causing the rest of the script to fail. Also why does a simple exception here cause so much CPU spike?
Strangely enough, no matter how I wrap an exception handler for ObjectDisposedException it never gets triggered, no matter how much code or where I wrap? (On both scripts)
try
{
tcpClient.EndConnect(ar);
}
catch (Exception ex)
{
connectException = ex;
}
I found out why, it wasnt because of the .EndConnect on either of the 2 files, it was actually caused by the .Close() calls, since it does .EndConnect inside of that, thats why I couldnt see any "Source" etc.
So it was causeed because the socket connection wasnt connected, so doing .Close() would cause the Exception.
It was a simple fix.
(Where tcp = a TcpClient)
Do the following instead of just tcp.Close()
On Timeouts (Where it's most likely if never at all connected):
if (tcp.Client.Connected) {
tcp.GetStream().Close();
tcp.Close();
}
When it might be properly connected:
if (!tcp.Connected) {
if (tcp.Client.Connected) tcp.GetStream().Close();
tcp.Close();
}
Using second-level retries in Rebus (https://github.com/rebus-org/Rebus/wiki/Automatic-retries-and-error-handling) I need to forward a message to an error queue after n retries.
This works:
_bus.Advanced.Routing.Send("my-queue.error",failedMessage.Message, failedMessage.Message);
But the exceptions accumulated in the failed message is not brought along, making the failed message in the error queue rather useless.
Ideally I would hook into the ITransport instance, and do something like this
await _transport.Send(errorQueueAddress, transportMessage, transactionContext);
(from PoisonQueueErrorHandler: https://github.com/rebus-org/Rebus/blob/333dbedf486acb92bd6c6250755537032c6215fd/Rebus/Retry/PoisonQueues/PoisonQueueErrorHandler.cs)
But there is no apparent way to get to that instance.
Any ideas on how to achieve this?
One way of forwarding the message to the error queue from your second level handler, is to simply throw exceptions – the usual n retries applies to 2nd level retries too, so if everything keeps failing, the message will eventually end up in the error queue.
If you're using Rebus version 6.2.1 or later, there's an extension method on ITransportMessageApi that enables you do manually dead-letter the message when you feel like it like this:
await bus.Advanced.TransportMessage.Deadletter("whatever error details you'd like to include!");
If you're on Rebus 6.7.0 or later, the Deadletter method has an overload that accepts an exception too, which lends itself nicely to do stuff like this:
try
{
// try something that can fail
}
catch (Exception exception)
{
await bus.Advanced.TransportMessage.Deadletter(exception);
}
The following answer is relevant for Rebus versions BELOW 6.2.1:
If you really want to emulate Rebus' behavior when forwarding the message to the error queue, you can get the full error details as they would have been included by Rebus via the ErrorDescription property on IFailed<YourMessage>.
You can then create these headers when forwarding the message:
var details = failedMessage.ErrorDescription;
var headers = new Dictionary<string, string>
{
{Headers.SourceQueue, "your-input-queue"},
{Headers.ErrorDetails, details}
};
and then you should forward the transport message to the error queue, thus preserving message identity and all other headers completely intact:
await bus.Advanced.TransportMessage.Forward("error", headers);
I think this would be the most realistic emulation of Rebus' behavior.
i am developing a wp8 app, i use a HttpClient to perform PostAsync and GetAsync operations, i am setting the timeout to 1 second :
private HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromMilliseconds(1000);
I have a try catch block on my Get and Post operation to caught the TimeOutExceptions as:
try
{
var response = await client.PostAsync(param1,param2);
}
catch (TimeoutException e)
{
//do something
}
Nevertheless my catch block is not capturing the exception, i debug my app and watch the throwen exception is a TaskCanceledException, ¿How can i caught the right exception?, ¿Why is the TimeOutException replaced?
Finally, and to avoid confusion, my real timeout will be 10 seconds, i am using 1 seconds just to test, and i need to show a message to the user if the timeout is exceeded.
On the HttpClicent PostAsync, the timeout is not sent as a TimeoutException. It is sent as a TaskCanceledException.
It is not 100% clear from the documentation, that I have seen, but the behaviour you are getting is the correct behavior. When the timeout is reached, TaskCanceledException is thrown.
This makes a little bit of sense if you look here | HttpClicent.Timeout Property
You may also set different timeouts for individual requests using a CancellationTokenSource on a task.
Suppose I create a HTTPWebRequest, call its GetResponse() and start reading from the response stream. If the connection is interrupted while reading from the stream, do I have to wait for it to time out, or can I know right away that something's gone wrong? No exception is thrown when I interrupt the connection (e.g. I disconnect my computer from the network).
It depends on the situation.
In general you'll need to be prepared for both situations (immediate and late interruption).
If, for example, the server disconnects you, you'll know relatively quickly.
See http://msdn.microsoft.com/en-us/library/system.net.webexceptionstatus for the kinds of errors that can occur (the WebRequest classes throw WebExceptions on errors)
You have a variety of options:
Use the async methods (BeginGet... and EndGet...) and model your application around this. Basically you'll be notified "at some point" if there was a success or error. Do something else in the meantime
If you want absolute control you can specify a ReadTimeout on the acquired stream (See comment on the other answer, set Timeout on the request as well). Re-try or whatever.
Just wait
You dont have to worry if the request is interrupted or not.
You can specify explicit timeout as follows.
If its interrupted you will get exception.
try
{
var request = HttpWebRequest.Create(url);
request.Timeout = 3000;
var response = request.GetResponse() as HttpWebResponse;
if (response.StatusCode.Equals(HttpStatusCode.OK))
{
//do stuff
}
}
catch (Exception exception)
{
exception.ToLog();
}
Most probably you have to wait for the timeout