A proper way to handle WCF network related exceptions - c#

In the application I"m working with, there is some communication with the remote service using WCF (basic http binding, no fancy stuff). Since the client is lightweigh, the details of the server are irrelevant, you may assume that there is just a method that always return true (like ping or something).
The proxy is generated using a Task option, the new client instance is created each time the operation is called. Something like this could be spinning inside the timer:
void Foo()
{
var client = new PingServiceClient();
try
{
bool result = client.PingAsync().GetAwaiter().GetResult();
}
catch
{
//log something
}
finally
{
client.Abort();
}
}
My question is, how should I correctly handle the cases when the network is down? Because the behavior is different. I either get an application crashing (I assume on a task finalizer, which is for some reason not handled neither in AppDomain.CurrentDomain.UnhandledException nor in TaskScheduler.UnobservedTaskException), or sometimes it just silently outputs tons of error messages, but not crashing anything. Messages like these:
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.Net.WebException' in System.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.AggregateException' in mscorlib.dll
I'm struggling to find a graceful way of handling these, so if anybody has some knowledge regarding this please share the approach.
Thanks in advance.
UPD:
I have tried to re-create the proxy with Begin/End pair and override the end method implementation in a partial class:
public partial class PingServiceClient : IPingServiceClient, PingService
{
public Task<bool> PingSync()
{
return Task.Factory.FromAsync(BeginPing(null, null), HandledEndPing);
}
private bool HandledEndPing(System.IAsyncResult result)
{
var res = false;
try
{
res = EndPing(result);
}
catch (Exception e)
{
;
}
return res;
}
}
Still the same barrage of messages in the output as before (the catch is working, though).

Related

.NET SignalR client crashing

I have a self-hosted Katana OWIN service with windows authentication (no https), that publishes a SignalR hub. Everything is at latest NuGet level, net4.6.2. The hub is publishing log events from NLog.
I need to access this hub from a WPF client. Just to make sure, I have a simple javascript client also, which is getting the messages as needed. But the c# client "crashes".
At an unpredictable point in time I see this in output window:
Exception thrown: 'System.InvalidOperationException' in System.dll
Exception thrown: 'System.InvalidOperationException' in System.dll
Exception thrown: 'System.ObjectDisposedException' in System.dll
Exception thrown: 'System.ObjectDisposedException' in System.dll
Exception thrown: 'System.ObjectDisposedException' in mscorlib.dll
And from that point on the On event is not fired anymore, even if not a single message arrived before:
public static async Task<bool> ConnectAsync()
{
var settings = new Properties.Settings();
Connection = new HubConnection(settings.WebAPI);
Connection.Credentials = CredentialCache.DefaultNetworkCredentials;
HubProxy = Connection.CreateHubProxy("NLogHub");
HubProxy.On<DTO.WebApi.List.Log>("logEvent", (logEvent) => {
Debug.WriteLine(logEvent.TimeStamp);
//LogEventArrived?.Invoke(logEvent);
});
try
{
ServicePointManager.DefaultConnectionLimit = 10;
await Connection.Start(new LongPollingTransport());
Connection.EnsureReconnecting();
}
catch (HttpRequestException)
{
return false;
}
return true;
}
I have tried other transports too, but no luck. Does not matter what is in the On event - can be fully empty, this still happens.
Both client and server are running now on Windows 2016. but server will be Windows 2012, clients Windows 7 for now.
[Update 1]
The exception is thrown/not catched somewhere inside SignelR client code. Depending on transport this is what I can get:
LongPollingTransport
WebSocketTransport
After adding trace, I have some more details (WebSocketTransport), but still no idea how to handle:
13:48:04.9934736 - b3378218-e7f5-4ab4-89f6-08e6579bc70a - WS: OnMessage({})
13:48:10.1545908 - b3378218-e7f5-4ab4-89f6-08e6579bc70a - OnError(System.TimeoutException: Couldn't reconnect within the configured timeout of 00:00:30, disconnecting.)
13:48:10.1595862 - b3378218-e7f5-4ab4-89f6-08e6579bc70a - Disconnected
Exception thrown: 'System.Net.Sockets.SocketException' in mscorlib.dll
13:48:10.1675878 - b3378218-e7f5-4ab4-89f6-08e6579bc70a - Transport.Dispose(b3378218-e7f5-4ab4-89f6-08e6579bc70a)
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
13:48:10.2616468 - b3378218-e7f5-4ab4-89f6-08e6579bc70a - Closed
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
Exception thrown: 'System.OperationCanceledException' in System.dll
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
As I mentioned before: the JavaScript client is working like a charm.
[Update 2]
All transports complain about n ot being able to reconnect. But nothing points on a connection lost. How to debug that?
Any idea is appreciated...

SoapException has the same message but in different forms

We have an ASP.NET project. The project is installed via InstallShield. We have a test method that throws SoapException and compares its message:
internal static string ExceptionMsgCheckForConflicts = "Server was unable to process request. ---> Rethrow exception, look at inner exception ---> System.ArgumentException ---> Item is invalid";
internal static string ErrorMsgCheckForConflictsInvalidException = "Exception should start with 'Server was unable to process request. ---> Rethrow exception, look at inner exception ---> System.ArgumentException ---> Item is invalid'";
[Test]
public void ConflictDetectorItemNotAnItemNode()
{
Assert.Throws<SoapException>(() =>
{
try
{
//Some code that throws SoapException
}
catch (SoapException ex)
{
Assert.IsTrue(ex.Message.StartsWith(ExceptionMsgCheckForConflicts, StringComparison.OrdinalIgnoreCase), ErrorMsgCheckForConflictsInvalidException);
throw;
}
});
}
The code works pretty well. But we decided to run this test on the installed version of project. The problem is that in this case exception is thrown with the message:
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Exception: Rethrow exception, look at inner exception ---> System.ArgumentException: Item is invalid
In fact it is the same message, but contains the names of exceptions. I and my boss have no idea why this happens.
I'm wondering if the odd try / catch / rethrow is causing the problem. Normally, using NUnit, one doesn't catch the exceptions one is asserting on. A simpler way to write the test would be...
var ex = Assert.Throws<SoapException>(() =>
{
// Code that throws SoapException
}
Assert.That(ex.Message.StartsWith(...));
BTW, I couldn't decide whether this was an answer or a comment, but answers make it easier to format code. :-)

Properly handling HttpClient exceptions within async / await

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.

CommunicationException is lifted, even in a try/catch block

I'm currently developping an application for WP7 that needs to make calls to a WCF Service Application. I tested the service with a small WPF application and everything went just fine. But now that I call it from my WP7 app, I systematically get the following exception :
An exception of type 'System.ServiceModel.CommunicationException' occurred in
System.ServiceModel.ni.dll but was not handled in user code
System.ServiceModel.CommunicationException was unhandled by user code
HResult=-2146233087
Message=The remote server returned an error: NotFound.
Source=System.ServiceModel
InnerException: System.Net.WebException
HResult=-2146233079
Message=The remote server returned an error: NotFound.
Source=System.Windows
InnerException: System.Net.WebException
HResult=-2146233079
Message=The remote server returned an error: NotFound.
Source=System.Windows
InnerException:
The exception keeps getting lifted despite the fact I make my service call within a try/catch block like this (in MyProjectPath.Model.User.cs) :
public Task<User> Load(string logon, string pwHash)
{
TaskCompletionSource<User> tcs = new TaskCompletionSource<User>();
client.GetUserByCredsCompleted += ((s, e) =>
{
if (e.Error == null) tcs.TrySetResult(e.Result);
else
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Error encountered while getting data :");
sb.AppendLine(e.Error.Message);
MessageBox.Show(sb.ToString());
}
});
try
{
client.GetUserByCredsAsync(logon, pwHash);
}
catch (System.ServiceModel.CommunicationException ex)
{
MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return tcs.Task;
}
And when executed, the exception occurs here (in System.ServiceModel.ni.dll) :
public MyProjectPath.ServiceReference.User EndGetUserByCreds(System.IAsyncResult result) {
object[] _args = new object[0];
// Exception gets lifted by the following line :
MyProjectPath.ServiceReference.User _result = ((MyProjectPath.ServiceReference.User)(base.EndInvoke("GetUserByCreds", _args, result)));
return _result;
}
Did anyone already encountered this problem and solved it ? I must admit I'm pretty clueless here...
You're calling an asynchronous API. Although you're wrapping that call in a try/catch block, that call will presumably be starting up a new thread or queueing a request for another existing thread to pick up. Either way, your try/catch is only protecting you against exceptions thrown on the thread which makes the call, and there aren't any. The (start of) your asynchronous call succeeds just fine, so the catch block never comes into effect, and then control is passed to the other thread and this is where the exception is thrown.
You can't protect against exceptions in EndGetUserByCreds by wrapping your call to GetUserByCredsAsync in a try/catch. The two methods are executing at different times different threads. You need to modify EndGetUserByCreds so that it catches exceptions and deals with them appropriately, rather than letting them crash the thread.

Catch Exception in AddInToken.Activate<T>()

I use MAF and I have a problem with activating the addin. Let me explain my plan.
First I create a secondary AppDomain then I try to activate the addin:
MyAddIn = Token.Activate<AddInHostView>(domain);
My AddIn is very simple and referenced only one helper assembly. If this helper assembly is in the directory of the AddIn, all things work like a charm.
AddIns
MyDemoAddIn.dll
Helpers.dll
If I delete the Helpers.dll the whole application crash:
A first chance exception of type 'System.IO.FileNotFoundException' occurred in MyDemoAddIn.DLL
'PresentationHost.exe' (Managed (v4.0.30319)): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll'
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in System.AddIn.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in System.AddIn.dll
I tested all things with exception handling. I can't catch the exception from the Host, AddInView or my created AppDomain :-(
Does anyone have an idea?
Your addin cannot run without Helpers.dll
Because it works across AppDomain boundaries, the addin needs it own set of DLLs to be loaded into its own AppDomain.
If you don't need cross AppDomain functionality, you can use Token.Activate<AddInHostView>(AppDomain.CurrentDomain) to load it if you have helpers.dll referenced in your host project.
The answer is easier than you think... The problem was a error in the Finalizer() Method from the AddInView.dll which is an interlayer of the MAF. Here is my solution.
Demo (Host)
try
{
MyAddIn = Token.Activate<AddInHostView>(domain);
}
catch (Exception ex)
{
try
{
AppDomain.Unload(domain);
domain = null;
}
catch (ThreadAbortException threadAbortException)
{
//ToDo: Logging
}
catch (CannotUnloadAppDomainException cannotUnloadAppDomainException)
{
//ToDo: Logging
}
catch (Exception exception)
{
//ToDo: Logging
}
}
AddInView
[AddInBase]
public class AddInView : UserControl
{
//Necessary constructor to handle the exception.
//Normal constructor is not called when an error occurs at startup!!!
static AddInView()
{
AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
}
//Normal constructor
public AddInView()
{
//Do other things...
//e.g. Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
static void CurrentDomain_DomainUnload(object sender, EventArgs e)
{
//To cleanup and stuff
}
}
Now, if an error occurs (Activate<>) the exception handler catches the error (FileNotFound Helpers.dll not found) and unload the whole AppDomain without crash the main AppDomain :-)

Categories