Best way to catch a WCF exception in Silverlight? - wcf

I have a Silverlight 2 application that is consuming a WCF service. As such, it uses asynchronous callbacks for all the calls to the methods of the service. If the service is not running, or it crashes, or the network goes down, etc before or during one of these calls, an exception is generated as you would expect. The problem is, I don't know how to catch this exception.
Because it is an asynchronous call, I can't wrap my begin call with a try/catch block and have it pick up an exception that happens after the program has moved on from that point.
Because the service proxy is automatically generated, I can't put a try/catch block on each and every generated function that calls EndInvoke (where the exception actually shows up). These generated functions are also surrounded by External Code in the call stack, so there's nowhere else in the stack to put a try/catch either.
I can't put the try/catch in my callback functions, because the exception occurs before they would get called.
There is an Application_UnhandledException function in my App.xaml.cs, which captures all unhandled exceptions. I could use this, but it seems like a messy way to do it. I'd rather reserve this function for the truly unexpected errors (aka bugs) and not end up with code in this function for every circumstance I'd like to deal with in a specific way.
Am I missing an obvious solution? Or am I stuck using Application_UnhandledException?
[Edit]
As mentioned below, the Error property is exactly what I was looking for. What is throwing me for a loop is that the fact that the exception is thrown and appears to be uncaught, yet execution is able to continue. It triggers the Application_UnhandledException event and causes VS2008 to break execution, but continuing in the debugger allows execution to continue. It's not really a problem, it just seems odd.

I check the Error property of the event args in the service method completed event handler. I haven't had issues with the event handler not being called. In the case where the server goes down, the call takes a few seconds then comes back with a ProtocolException in the Error property.
Assuming you have tried this and your callback really never gets called, you might look into customizing the generated proxy class. See this article.

I found a forum thread that was talking about this, and it mentions that the best practice is to use the Error property. Between this thread and my own experiences, this is what I can conclude:
In normal .NET code, the generated proxy class handles the exception properly by putting the exception in the Error property instead of throwing it.
In Silverlight, the generated proxy class sets the Error property, but does not handle the exception completely. The exception is picked up by the debugger, which pops up the exception box with the message "ProtocolException was unhandled by user code". Despite this message, the exception does not seem to actually make it to the Application_UnhandledException function.
I'd expect that this is one of the things they will fix in the final release.
For now, I will use the Error property and just deal with the debugger breaking execution. If it gets too annoying, I can turn off the break on exception for ProtocolException.

You can forget about Application_UnhandledException on asyn client callbacks, reason why:
Application_UnhandledException only exceptions fired on the UI thread can be caught by Application.UnhandledExceptions
This means... not called at all for a WCF async call :-).
Check detailed response from MSFT
http://silverlight.net/forums/t/21828.aspx
Hello, only exceptions fired on the UI thread can be caught by Application.UnhandledExceptions. It can't catch exceptions from other threads. You can try this to trouble shoot the issue: In Visual Studio, from the Debug menu, choose Exceptions. Then check "Common Language Runtime Exceptions". This will make the debugger stop whenever an exception is thrown. But note this may be quite annoying sometimes since even if an exception is already caught. You can use the CheckBoxes to filter the exceptions you want to catch.
Good news in my case is that handling the error message just in the clietn service call back is enough if you are not debugging.
Thanks
Braulio

OOpps....
Sorry wrong answer from my side (well the MSFT guy didn't hit the write answer service callbacks are called on the same UI thread), the thing is
More info:
- In development even detaching from the debugger, this method is never reached.
- On the production environment yes.
My guess something related with Visual Studio options and intercepting exceptions.
More info, in this thread
http://silverlight.net/forums/p/48613/186745.aspx#186745
Quite interesting topic.

With Silverlight 3 the the Visual Studio debugger catches these exceptions so that the exception handler - confusingly - is never reached. However, when running without the debugger, the exception handler is called as expected. I guess this is ok as long as one is aware of it. I admit i wasted a few hours trying to figure out how to drill into the inner workings of Silverlight/Wcf/Browser to get to my exception. Don't go there.

I'm not a plumber, so I decided to create my own WCF service class that overrides some of the functionality of the class file "reference.cs" that is automatically generated by Visual Studio, I then added my own try/catch blocks to catch communication errors.
The class I created looks something like this:
public class myWCFService : MyWCFServiceClient
{
protected override MyController.MyService.IMyWCFService CreateChannel()
{
return new MyWCFServiceClientChannel(this);
}
}
private class MyWCFServiceClientChannel : ChannelBase<MyController.MyService.IMyWCFService>, MyController.MyService.IMyWCFService
{
/// <summary>
/// Channel Constructor
/// </summary>
/// <param name="client"></param>
public MyWCFServiceClientChannel(System.ServiceModel.ClientBase<MyController.MyService.IMyWCFService> client) :
base(client)
{
}
/// <summary>
/// Begin Call To RegisterUser
/// </summary>
/// <param name="memberInformation"></param>
/// <param name="callback"></param>
/// <param name="asyncState"></param>
/// <returns></returns>
public System.IAsyncResult BeginRegisterUser(MyDataEntities.MembershipInformation memberInformation, System.AsyncCallback callback, object asyncState)
{
object[] _args = new object[1];
_args[0] = memberInformation;
System.IAsyncResult _result = base.BeginInvoke("RegisterUser", _args, callback, asyncState);
return _result;
}
/// <summary>
/// Result from RegisterUser
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public MyDataEntities.MembershipInformation EndRegisterUser(System.IAsyncResult result)
{
try
{
object[] _args = new object[0];
MyDataEntities.MembershipInformation _result = ((MyDataEntities.MembershipInformation)(base.EndInvoke("RegisterUser", _args, result)));
return _result;
}
catch (Exception ex)
{
MyDataEntities.MembershipInformation _result = new MyDataEntities.MembershipInformation();
_result.ValidationInformation.HasErrors = true;
_result.ValidationInformation.Message = ex.Message;
return _result;
}
}
}

Using a custom WCF Proxy generator is a good solution to handle asynchronous exceptions in Silver-light.Click here to download source code.

With XNA on WP7, I found I had no choice but to manually add try/catch to the various async End*FunctionName*() methods; nothing else I tried would prevent application failure & shutdown when the server was unavailable. It's a real drag having to manually update this code when a service changes.
I am surprised this isn't a bigger issue since there doesn't seem to be any other way to catch these exceptions on WP7 using XNA but I suppose this just says more about how many (==not many) people are trying to do this than anything else. If they would just make slsvcutil.exe generate sync methods we could easily catch these within our own worker thread, but unfortunately the generated code uses thread pool threads with no means to catch the exceptions.

To Handle this situation use the TargetInvocationException. This will catch the Exception when the network is down or your service is unavailable.

Related

Is it necessary to explicitly Invoke calls to COM object's thread?

I am using a 3rd party Activex control from .NET. I have successfully created the RCWs (AxInterop.ACMELib.dll and Interop.ACMELib.dll) by adding a reference to the ActiveX ocx and dragging a control onto my form.
At this point, the interface that the RCW provides is lacking and I've decided to create my own Component as an additional wrapper. One reason is that I access the RCW from many threads and I wanted to synchronize access to the RCW to only one thread at a time. My class looks like:
Public Class ACMEWrapper ' my Component
Inherits AxACMELib.ACMEClass
Public Overrides Function GetData() As Int()
Dim result As Int()
Try
SyncLock LockACMEObject
result = MyBase.GetData()
End SyncLock
Return result
Catch
' log exception, etc.
End Try
End Function
This class works fine in most cases. However, there are times when my application crashes with no Exception that can be handled by my application. Not even from a catch-all unhandled exception handler. In some cases it does actually catch an "External component has thrown an exception..." from which I cannot recover.
I thought i had tried everything until on a whim I explicitly Invoked all calls to the RCW on the thread it was created on i.e.
MyBase.Invoke(Sub() result = MyBase.GetData())
My application no longer crashes in this manner. I've searched the web for a justification for my actions as when something works I want to know why it worked. Finding nothing, I decided to post this question. Can someone tell me why what I did is working, and guide me to some literature with more information on this subject?

IErrorHandler interface is confusing me

I have created a class that implements IErrorHandler and IServiceBehavior. I add the behavior to my ServiceHost and run it.
The reason I got around to trying to learn about IErrorHandler is because the frustration I was having in having to wrap all of my service code that interfaces with callback channels in try catch statements, and wondered if there was a global way to catch the exceptions.
Well from what I read here on StackOverflow, I saw that it is indeed the thing I want.
In execution however, it's confusing me greatly. If I have a contract method that does the following...
Dictionary<IChatCallback, string> userChannels = new Dictionary<IChatCallback, string>();
public void SendMessage(string message)
{
IChatCallback callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
string senderName = userChannels[callback];
SendMessageToAllUsers(message, senderName);
}
public void SendMessageToAllUsers(string message, string sender)
{
foreach (var userChannel in userChannels.Keys)
{
userChannel.ReceiveMessage(new ChatMessage(message, sender));
}
}
If a client is on my server and he drops off the face of the earth and the channel faults, it seems to take a while before my server realizes that the channel is faulted. Even if am subscribed to the events of the ICommunicationObject, it seems to take a while before the server realizes the channel is faulted. For example, if someone is sending messages and someone disconnects, and a message is being propagated at the same time.
Now, I have another method that essentially pings clients at a regular interval to figure out if they're still there or not, so I can remove them from the userChannel dictionary.
How exactly is IErrorHandler supposed to help me here? It seems that it's not exactly helping my service from crashing even if it catches the error. Because my service cannot ping my clients at a super rapid pace, sometimes a message seems to come in immediately(I was testing this) after a previous message that threw an exception. It seemed to have handled the first one, but the second one threw another exception that wasn't caught, and my service crashed, because the server was trying to communicate with a faulted channel. Now, my service DOES clean up those faulted channels, but it does so periodically.
I was hoping that by implementing IErrorHandler I could avoid having to wrap all of my methods in try{}catch{} blocks... but it seems like I still have to, to check if I'm communicating with a faulted channel?
Or maybe I'm just going about using IErrorHandler improperly and thinking it should be doing things it's not supposed to do. Should I maybe have my service implement it, and inject itself into the Servicehost as the IServiceBehavior? And then in my HandleError() method remove the channel from my list of clients? That seems kind of messy, because I'm putting that WCF plumbing stuff in my service class, but that would be the only way I can think of to have the exception code itself remove the channel from the list of callbacks.
I'm trying to do a lot of reading because I'm new to it, but it seems like the world of Error Handling in WCF is daunting.
Even if I try to remove the channel so it's not called on services via subscribing to the Faulted event, it doesn't work fast enough and still throws exception that the server cannot seem to recover from even with IErrorHandler.
For example, when the user first connects, I subscribe to the event.
IChatCallback callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
ICommunicationObject callbackComm = (ICommunicationObject) callback;
callbackComm.Faulted += (sender, e) =>
{
lock (lockObject)
{
string name = userChannels[callback];
userChannels.Remove(callback);
NotifyOfUserDisconnect(name);
}
};
Do I just need to go into all my methods and check if the channel is closed or faulted, and wrapping everything in a try/catch block to remove the reference and notify clients?

WCF + Enterprise Library + ValidationFault

I am trying to catch the ValidationFault exceptions of my service and return a instance of MyClass with the property Message filled with the validation error provided by EntLib when my client calls one of my service methods without the correct parameters (I can't use complex types).
I tried to implement two interfaces to accomplish this task: IParameterInspector and IOperationInvoker. The problem is after the method BeforeCall is called (of the IParameterInspector interface), EntLib throws the ValidationFault exception but I can't catch it and my code doesn't reach the Invoke method of my IOperationInvoker class and because of that I can't replace the return value with a instance of MyClass.
Remember, my client is not based on .NET platform and there's no such thing as catch(FaultException<ValidationFault> ex) there. That's why I MUST work with a default object on my service responses.
I appreciate the help.
Can you use an IErrorHandler implementation similar to Enterprise Library's WCF ExceptionShielding? Basically catch all exceptions and if it's a FaultException<ValidationFault> then convert the ValidationFault to your custom message and return it.
It looks like the output of ProvideFault is a Message so you could return a message instead of a fault. This posting seems to give the approach.

Calling Abort on faulted WCF channel causes server side error to be logged

When a FaultException is returned from my WCF service, I need to Abort the channel instead of Closing it. Both my client and service work fine with this approach but after implementing IErrorHandler on the service and logging any exception, I can see that calling Abort on the client causes the service to log:
System.ServiceModel.CommunicationException: The socket connection was aborted...
I do not want to pollute my service logs with this information and only want to log service related errors. I know I can obviously stop logging any CommunicationExceptions but my service is also a WCF client for other services and CommunicationExceptions raised by these services should be logged.
How can I stop it doing this?
As nobody else has answered the question (Tomas's answer was not relevant), I asked a few experts in the field. Unfortunately, there is no nice way of stopping this and the best that they could come up with was to add logic in IErrorHandler to not log CommunicationExcepions with a message starting with 'The socket connection was aborted'. Not very elegant, but it does work.
The problem is that you get an exception that covers your underlying exception if you get an exception when calling dispose wich is possible. I wrote a wrapper to deal with scenarios like this, you can read about it on my blog: http://blog.tomasjansson.com/2010/12/disposible-wcf-client-wrapper/
The idea is that you have a wrapper around your channel that deals with the scenario if the dispose method throws an exception.
A small example of how you should use my wrapper:
public class ClientWrapperUsage : IYourInternalInterface
{
public IList<SomeEntity> GetEntitiesForUser(int userId)
{
using(var clientWrapper = new ServiceClientWrapper<ServiceType>())
{
var response = clientWrapper.Channel.GetEntitiesForUser();
var entities = response.YourListOfEntities.TranslateToInternal();
return entities;
}
}
}
Here I have assumed that it existing an extension method for a list that contains the entity that is returned by the service, then you use that method to translate it to internal entities. This is 100 % testable, at least I think :). Just moch the interface IYourInternalInterface everywhere you wan't to fake the service.

WCF - Faults / Exceptions versus Messages

We're currently having a debate whether it's better to throw faults over a WCF channel, versus passing a message indicating the status or the response from a service.
Faults come with built-in support from WCF where by you can use the built-in error handlers and react accordingly. This, however, carries overhead as throwing exceptions in .NET can be quite costly.
Messages can contain the necessary information to determine what happened with your service call without the overhead of throwing an exception. It does however need several lines of repetitive code to analyze the message and determine actions following its contents.
We took a stab at creating a generic message object we could utilize in our services, and this is what we came up with:
public class ReturnItemDTO<T>
{
[DataMember]
public bool Success { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public T Item { get; set; }
}
If all my service calls return this item, I can consistently check the "Success" property to determine if all went well. I then have an error message string in the event indicating something went wrong, and a generic item containing a Dto if needed.
The exception information will have to be logged away to a central logging service and not passed back from the service.
Thoughts? Comments? Ideas? Suggestions?
Some further clarification on my question
An issue I'm having with fault contracts is communicating business rules.
Like, if someone logs in, and their account is locked, how do I communicate that? Their login obviously fails, but it fails due to the reason "Account Locked".
So do I:
A) use a boolean, throw Fault with message account locked
B) return AuthenticatedDTO with relevant information
This however carries overhead as throwing exceptions in .NET can be quite costly.
You're serializing and de-serializing objects to XML and sending them over a slow network.. the overhead from throwing an exception is negligable compared to that.
I usually stick to throwing exceptions, since they clearly communicate something went wrong and all webservice toolkits have a good way of handling them.
In your sample I would throw an UnauthorizedAccessException with the message "Account Locked".
Clarification: The .NET wcf services translate exceptions to FaultContracts by default, but you can change this behaviour. MSDN:Specifying and Handling Faults in Contracts and Services
If you think about calling the service like calling any other method, it may help put things into perspective. Imagine if every method you called returned a status, and you it was up to you to check whether it was true or false. It would get quite tedious.
result = CallMethod();
if (!result.Success) handleError();
result = CallAnotherMethod();
if (!result.Success) handleError();
result = NotAgain();
if (!result.Success) handleError();
This is one of the strong points of a structured error handling system, is that you can separate your actual logic from your error handling. You don't have to keep checking, you know it was a success if no exception was thrown.
try
{
CallMethod();
CallAnotherMethod();
NotAgain();
}
catch (Exception e)
{
handleError();
}
At the same time, by returning a result you're putting more responsibility on the client. You may well know to check for errors in the result object, but John Doe comes in and just starts calling away to your service, oblivious that anything is wrong because an exception is not thrown. This is another great strength of exceptions is that they give us a good slap in the face when something is wrong and needs to be taken care of.
I would seriously consider using the FaultContract and FaultException objects to get around this. This will allow you to pass meaningful error messages back to the client, but only when a fault condition occurs.
Unfortunately, I'm in a training course at the moment, so can't write up a full answer, but as luck would have it I'm learning about exception management in WCF applications. I'll post back tonight with more information. (Sorry it's a feeble answer)