How can i manage exceptions from Client.PostAsync<T>? [duplicate] - c#

I was hoping somebody could enlighten me a little bit on an issue I am facing in regards to async/await exception handling with HttpClient. I have written some code to illustrate, and it is being excecuted on both a Windows Phone 8 device and the emulator:
private async void SearchButton_Click(object sender, EventArgs e)
{
try
{
HttpClient client = new HttpClient();
System.Diagnostics.Debug.WriteLine("BEGIN FAULTY REQUEST:");
string response = await client.GetStringAsync("http://www.ajshdgasjhdgajdhgasjhdgasjdhgasjdhgas.tk/");
System.Diagnostics.Debug.WriteLine("SUCCESS:");
System.Diagnostics.Debug.WriteLine(response);
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine("CAUGHT EXCEPTION:");
System.Diagnostics.Debug.WriteLine(exception);
}
}
Tapping the button that invokes this function, produces the following output in the debugger console, the most interesting being the ones in bold:
BEGIN FAULTY REQUEST:
An exception of type 'System.Net.WebException' occurred in System.Windows.ni.dll and wasn't handled before a managed/native boundary
An exception of type 'System.Net.WebException' occurred in System.Windows.ni.dll and wasn't handled before a managed/native boundary
A first chance exception of type 'System.Net.Http.HttpRequestException' occurred in mscorlib.ni.dll
An exception of type 'System.Net.Http.HttpRequestException' occurred in mscorlib.ni.dll and wasn't handled before a managed/native boundary
CAUGHT EXCEPTION:
(and here it prints out the HttpRequestException)
Of course I am expecting an error in this case since the URL I am calling is nonsense. What I am not understanding here, is why the debugger reports that the exceptions are not handled, when the output simultaneously reports that the exception is caught. Also, the UI side of the app becomes much less responsive while the output is being printed, indicating that something is probably amiss.
Is this not the way to handle exceptions when working with async and await? I appreciate any input! Thanks.

As you are using HttpClient, try to use response.EnsureSuccessStatusCode();
Now HttpClient will throw exception when response status is not a success code.
try
{
HttpResponseMessage response = await client.GetAsync("http://www.ajshdgasjhdgajdhgasjhdgasjdhgasjdhgas.tk/");
response.EnsureSuccessStatusCode(); // Throw if not a success code.
// ...
}
catch (HttpRequestException e)
{
// Handle exception.
}
ORIGINAL SOURCE OF THE CODE: http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

This is an artifact of the debugger. It's determining that an exception is "uncaught" because it's not caught yet. In this case this is expected behavior.
You are handling the exceptions correctly.

The debugger is telling you that this exception is first chance. When a debugger is attached to your process it gets notified for every exception that is thrown and then based on how the debugger has been configured it will decide what to do with it. You can go through What is first chance exception? for more details.
On a side note, catch specific exceptions only so that you understand which exceptions you are expecting and why.

Related

Exception in async/await not caught

I do not understand why an exception thrown inside an async method is not caught when the await statement is surrounded by a try/catch, which becomes an unhandled exception crashing the app.
The reason for this exception is understood, I'm not expecting an answer for that. I was assuming the exception would be caught. I'm worried about the exception handling in the application not doing what is expected on future exceptions.
using Amazon.Lambda.Model;
InvokeResponse invokeResponse;
var lambdaRequest = new InvokeRequest {...};
try
{
var task = _awsLambdaClient.InvokeAsync(lambdaRequest);
invokeResponse = await task; <<== throws TaskCanceledException
}
catch (Exception e)
{
Log.Error(...);
return
}
C# environment is Mono, Xamarin.Android to be specific, though I imagine the same code compiled in a .NETCORE console app would repro as well, unless this is a bug in Mono which I doubt. I assume I'm misunderstanding something about exception handling.
UPDATE:
Tried the same code in a .NETCORE20 console application, and the TaskCanceledException is handled. So it's looking like a Mono/Xamarin.Android specific problem.
New Update: After being able to repro this for a few days, of course my repro stopped repro'ing and the exception is now caught in the Mono app too. Not really sure what happened.

Visual studio breaks on exception that IS handled with unhandled exception dialog

My code calls a WCF service that is current not running. So we should expect the EndPointNotFoundException. The using statement tries to Close() the faulted connection which causes a CommunicationObjectFaultedException which is excepted. This exception is caught in a try catch block surrounding the using block:
class Program
{
static void Main()
{
try
{
using (ChannelFactory<IDummyService> unexistingSvc = new ChannelFactory<IDummyService>(new NetNamedPipeBinding(), "net.pipe://localhost/UnexistingService-" + Guid.NewGuid().ToString()))
{
using (IClientChannel chan = (unexistingSvc.CreateChannel() as IClientChannel))
{
(chan as IDummyService)?.Echo("Hello");
}
}
}
catch (EndpointNotFoundException ex)
{
Console.WriteLine("Expected");
}
catch (CommunicationObjectFaultedException ex)
{
Console.WriteLine("Expected: caused by closing channel that has thrown EndPointNotFoundException");
}
}
}
Note the service EndPoint uses a fresh Guid so it will never have a service listening.
IDummyService is:
[ServiceContract]
interface IDummyService
{
[OperationContract]
string Echo(string e);
}
This causes the Visual Studio debugger (Visual Studio Professional 2017 15.4.1) to break with an "Exception Unhandled" popup:
The exception on which Visual Studio breaks is System.ServiceModel.CommunicationObjectFaultedException which is caught in the code.
Stepping to continue execution shows that catch(CommunicationObjectFaultedException ex) is reached. Using LinqPad to run the demo also shows that the exception is caught as expected.
I also tried explicitly (double) closing the channel instead of using the using-block:
class Program
{
static void Main()
{
try
{
using (ChannelFactory<IDummyService> unexistingSvc = new ChannelFactory<IDummyService>(new NetNamedPipeBinding(), "net.pipe://localhost/UnexistingService-" + Guid.NewGuid().ToString()))
{
IDummyService chan = null;
try
{
chan = unexistingSvc.CreateChannel();
chan.Echo("Hello");
}
catch (EndpointNotFoundException ex)
{
Console.WriteLine($"Expected: {ex.Message}");
}
finally
{
try
{
(chan as IClientChannel)?.Close();
}
catch (CommunicationObjectFaultedException ex)
{
Console.WriteLine($"Caused by Close: {ex.Message}");
}
}
}
}
catch (EndpointNotFoundException ex)
{
Console.WriteLine("Expected");
}
catch (CommunicationObjectFaultedException ex)
{
Console.WriteLine("Expected: caused by closing channel that has thrown EndPointNotFoundException");
}
}
}
This still causes the debugger to break on the Close statement.
My Exception Settings has System.ServiceModel.CommunicationObjectFaultedException unchecked. (When it is checked Visual studio breaks as expected and with the "Exception Thrown" dialog instead of the "Exception Unhandled" dialog).
When I enable "Options"\"Debugging"\"General"\"Enable Just My Code" the debugger does not break. However, I have async methods where the exception should leave my code and I later catch the exception when awaiting the Task. For these methods I need "Enable Just My Code" unchecked; see Stop visual studio from breaking on exception in Tasks.
With "Using the New Exception Helper" disabled (as suggested by Jack Zhai-MSFT) Visual Studio still breaks and it shows
The dialog provides some additional information:
The exception is not caught before it crosses a managed/native boundary.
I suspect that the using block probably introduces this managed/native boundary.
What causes the debugger to break by mistake and how to make the debugger not break neither or handled CommunicationObjectFaultedExceptions nor on later handler async exceptions?
The new Exception feature was in VS2017, we could disable debugging option "Use the New Exception Helper" under TOOLS->OPTION->Debugging->General which could provide you the old Exception messages, you could visit it.
The old Exception Message shows that the Exception crosses a managed/native boundary:
Check "Break when Exceptions cross AppDomain or managed/native boundaries" under TOOLS->OPTION->Debugging->General. Disable "Break when Exceptions cross AppDomain or managed/native boundaries" to avoid Visual Studio breaking on the OP's situation (be careful though since this also disables breaking on other situations where an exception crosses an AppDomain or managed/native boundary).
Close()-ing a Faulted IClientChannel causes a CommunicationObjectFaultedException:
public void Close(TimeSpan timeout)
{
...
switch (originalState)
{
case CommunicationState.Created:
case CommunicationState.Opening:
case CommunicationState.Faulted:
this.Abort();
if (originalState == CommunicationState.Faulted)
{
throw TraceUtility.ThrowHelperError(this.CreateFaultedException(), Guid.Empty, this);
}
break;
...
}
...
}
-- (See CommunicationObject.Close(TimeSpan) line #299 in the .NET framework 4.7 reference source).
The using-block is translated to try { ... } finally { Dispose(); } and Dispose() calls Close() when the block is left. The proxy returned by CreateChannel() is implemented via RealProxy (src) and RemotingServices.CreateTransparentProxy() these proxy combine managed and unmanaged code, which might cause the exception crossing the boundary.
The combination of settings (in TOOLS->OPTIONS->Debugger->General):
☑ Break when Exceptions cross AppDomain or managed/native boundaries
☐ Enable Just My Code
Causes Visual Studio to break showing either: the new non-modal exception popup "Exception Unhandled":
or the modal dialog:
The CommunicationObjectFaultedException starts in 'Not My Code'; it crosses an managed/unmanaged or AppDomain boundary while still being in 'Not My Code'; and finally enters 'My Code' where it is handled by the catch-block (but Visual Studio has already halted the excuting at this point).
Since the exception starts in 'Not My Code' and remains there when crossing the boundary, selecting the option "Enable Just My Code" causes Visual studio to not break on the exception even when it crosses the AppDomain or managed/unmanaged boundary.
Deselecting "break when exceptions cross AppDomain or managed/native boundaries" also causes Visual Studio to not break on the exception.
This gives two solutions/workarounds
Choose a different combination of "Break when Exceptions cross AppDomain or managed/native boundaries" and "Enable Just My Code"
Do not use a using-block for the IClientChannel and check IClientChannel.State before Close()-ing. As is done in What is the best workaround for the WCF client `using` block issue?

Roslyn scripting engine does not throw runtime exception when used as delegate

I run into troubles using the Roslyn Scripting Engine. I get no exception handling when I run a script within a delegation.
Test that works as expected:
string script = #"var a=0; var b=2/a;";
var runner = CSharpScript.Create<object>(script);
var errors = runner.Compile();
Assert.IsTrue(errors.IsEmpty);
try
{
runner.RunAsync();
Assert.Fail("Where is the exception");
}
catch (System.Exception)
{
// everything is OK! Error thrown...
}
Result: No Assertion. The Exception was thrown.
Here's the text using a delegate object:
Unittest:
string script = #"var a=0; var b=2/a;";
var runner = CSharpScript.Create<object>(script);
var errors = runner.Compile();
var delegat = runner.CreateDelegate();
Assert.IsTrue(errors.IsEmpty);
try
{
delegat();
Assert.Fail("Where is the exception?");
}
catch (System.DivideByZeroException)
{
// everything is OK! Error thrown...
}
I got the fail message and no exception was thrown.
We cache the delegates to speed up the compilation and during a test we see that runtime exceptions are not thrown. So I wrote the test to reproduce this situation.
I can't find any hint in the docs which describes that there are no exceptions thrown during the invoke.
Can someone give me a pointer or a hint why this happens?
There are two issues with your code:
In the first version, you're catching Exception, which means that when the Assert.Fail is reached and throws AssertionException, that exception is then caught and ignored.
This means that there is no difference between RunAsync and delegate here, neither of them throws DivideByZeroException.
Both RunAsync and the ScriptRunner<T> delegate return Task. That means to actually wait for them to complete or to observe any exceptions, you need to use await. Once you do that, you will see the DivideByZeroException that you're expecting.
Your Main finishes execution before the scheduler gets a chance to invoke delegat. It is a task that will run asynchronously. You can see that when you inspect it in the debugger:
To force execution inside the scope of the try...catch, you can use this:
try
{
delegat().Wait();
}
catch(System.AggregateException ex)
{
/* the inner exception of ex will be your DivideByZeroException */
}
The correct type of exception to expect in this case is the AggregateException, see here why.
A solution with await is also possible:
await delegat();
but this will compile only when the containing method can be marked async which is not necessarily what you want (show more of the calling code to clarify).

How to fix "'System.AggregateException' occurred in mscorlib.dll"

I'm receiving an unhandled exception while debugging, and the program stops executing. The debugger doesn't show me the line so I don't know what to fix.
An unhandled exception of type 'System.AggregateException' occurred in mscorlib.dll
Additional information: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
Cannot obtain value of local or argument '<this>' as it is not available at this instruction pointer, possibly because it has been optimized away. System.Threading.Tasks.TaskExceptionHolder
How can I troubleshoot this problem?
I also found this question which is pretty similar.
As the message says, you have a task which threw an unhandled exception.
Turn on Break on All Exceptions (Debug, Exceptions) and rerun the program.
This will show you the original exception when it was thrown in the first place.
(comment appended): In VS2015 (or above). Select Debug > Options > Debugging > General and unselect the "Enable Just My Code" option.
You could handle the exception directly so it would not crash your program (catching the AggregateException). You could also look at the Inner Exception, this will give you a more detailed explanation of what went wrong:
try {
// your code
} catch (AggregateException e) {
}
The accepted answer will work if you can easily reproduce the issue. However, as a matter of best practice, you should be catching any exceptions (and logging) that are executed within a task. Otherwise, your application will crash if anything unexpected occurs within the task.
Task.Factory.StartNew(x=>
throw new Exception("I didn't account for this");
)
However, if we do this, at least the application does not crash.
Task.Factory.StartNew(x=>
try {
throw new Exception("I didn't account for this");
}
catch(Exception ex) {
//Log ex
}
)
In my case I ran on this problem while using Edge.js — all the problem was a JavaScript syntax error inside a C# Edge.js function definition.

Catch block for System.ArgumentException exists, but exception is not caught anyway, why?

I have this code:
if (typeof(Enum).IsAssignableFrom(typeof(T)))
{
try
{
return (T)Enum.Parse(typeof(T), text);
}
catch (ArgumentException e)
{
return default(T);
}
}
However I received the following exception:
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Requested value 'ABC' was not found
How is that possible? Why is the catch block not working?
Why is the catch block not working?
The catch block is working perfectly fine, it's just that you are looking this in Visual Studio debugger. That's what a first chance exception means. When you debug, all exception are shown in VS, it's just that a first chance exception might disappear if you have a proper catch clause. And by the way you could configure VS not to show them.
Oh and just a side note: in .NET 4.0 there's the Enum.TryParse method so you don't even need to try and catch in this particular snippet.
A first-chance notification is just to let the debugger know that the exception was thrown - this happens before any catch frames are considered. So in short your exception is (probably) caught.

Categories

Resources