24

I have a WCF service deployed on two or more remote machines and there is a desktop based application that is used by the client to access any wcf service.

The WCF service is connected to SQL server 2005 to read and write data. This is an intranet scenario in which the client should be on same domain.

Now there can be scenarios where the wcf service throws exceptions:

  1. Invalid URL
  2. WCF service is down
  3. SQL server 2005 is not running
  4. Client is not on the same domain
  5. Authentication fails
  6. Authorization fails

and many other exceptions.

For every exception I have to perform some action or update a status bar, depending on the exception. For example if authorization fails I have to prompt the user to re-enter their credentials.

Please suggest the best design approach to handle this.

Daniel Robinson
  • 2,165
  • 17
  • 14
Ashish Ashu
  • 14,169
  • 37
  • 86
  • 117

4 Answers4

35

You can definitely catch and handle all exceptions that happen on your service class and turn them into a FaultException or FaultException exception.

That way, you won't "fault" (or tear down) the communications channel between your client and server.

Even better approach would be to implement the IErrorHandler interface on your service class that provides a way to globally catch all exceptions as they happen and provide a FaultException instead, that's SOAP compliant.

You can even turn your IErrorHandler into a configurable behavior that can be turned on or off in config.

See these articles and blog posts for more details:

Community
  • 1
  • 1
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    I don't know much on IErrorHandler but I read articles and posts on using IErrorHandler it says it has some disadvantages. In some cases exception may directly be thrown from the wcf service to the client. Would you recommend me for IErrorHandler ?? – Ashish Ashu Oct 08 '09 at 08:55
  • Yes, by all means - I would **always** recommend using IErrorHandler. Can you post the links to these articles that say it has disadvantages?? Never heard of those - I'd like to investigate.... – marc_s Oct 08 '09 at 08:56
  • http://stackoverflow.com/questions/265551/wcf-errorhandler Read the second post!! I don't know wheather it's correct or not but it always creates the confustion in my mind – Ashish Ashu Oct 08 '09 at 09:01
  • 4
    Well, I guess he's expecting too much - IErrorHandler will catch all exceptions that occur ON THE SERVER - a communications error, or a mismatch in security settings, does not happen on the server - but before the message even reaches the server. This is a different scenario. – marc_s Oct 08 '09 at 09:32
  • 1
    May I point you straight to Rory Primrose's post. It's a complete working example. – harvest316 Sep 26 '13 at 11:07
  • @marc_s I realize this is a very old thread, but I'm running into the exact same issue (SecurityExceptions not caught by IErrorHandler). You say it does not happen on the server which is confusing me. The ServiceCredentials behavior is attached in the service host and does execute on the server (my WCF tracing captures the exception just fine). Is there a way to capture these exceptions? – MvdD May 01 '15 at 21:55
  • How can I efficiently handle errors an exceptions of any type in the client side only (I am only the consumer, the server code is beyond me). Please refer to [this](http://stackoverflow.com/q/33734660/75500) question I posted. – Shimmy Weitzhandler Nov 17 '15 at 13:43
  • @marc_s, When I am calling my WCF Service from jquery ajax method, I always get error response in plain html format. When I parse the response using $.parseJSON() method, Invalid json format error is coming. How can I receive my error response in json format from WCF service? – RGS Mar 29 '16 at 17:50
6
  1. Create a custom fault class that is marked with the DataContract attribute
  2. Mark the method on the service contract interface with FaultContract. Ie. [FaultContract(typeof(CustomFault))]
  3. In your service method, catch any applicable internal exceptions and throw a FaultException<CustomFault>. Alternatively, as marc_s mentioned, you can use IErrorHandler to map the exception to the fault.

Personally, I create a base Fault class that has a Reason property and I extend all custom faults from this class. When I want to throw the fault, I call:

throw Fault.Create<CustomFault>(new CustomFault("Boo hoo"));

It's also worth noting that I version my fault classes (including the common Fault class) along with all my other services. This is only a concern if service versioning is a concern, though.

Here's the basic Fault class (I've removed argument validation for brevity):

[DataContract(Namespace = XmlVersionNamespace.FaultNamespace)]
public abstract class Fault
{
    internal FaultReason Reason { get; set; }

    protected Fault(string reasonText)
    {
        Reason = new FaultReason(new FaultReasonText(reasonText, CultureInfo.CurrentUICulture));
    }

    public override string ToString()
    {
        return Reason.ToString();
    }

    internal static FaultException<TDetail> Create<TDetail>(TDetail fault) where TDetail : Fault
    {
        return new FaultException<TDetail>(fault, fault.Reason);
    }
}
Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
  • Thanks Richard ! Can you please give me an example if suppose authentication fails. Just give me the class relation ships and how you will handle on client app.. – Ashish Ashu Oct 08 '09 at 08:57
  • I would create an AuthenticationFailedFault (extend it from Fault), passing a message to the base Fault constructor. In your client app, you just catch FaultException, since AuthenticationFailedFault will be part of the WSDL (as long as you marked the method with [FaultContract]) – Richard Szalay Oct 08 '09 at 10:09
2

You can design the specific Fault Data Contracts for each of the exception scenario in your WCF service so that you can handle the fault/exception at client side respectively.

Ray Lu
  • 26,208
  • 12
  • 60
  • 59
1
try
{
  // Actions
}
catch (Exception ex)
{
  // Log the exception
  // Throw Fault Exception back to client
  FaultException fe = new FaultException(ex.Message, new FaultCode("Your fault code"));
  //throw fault exception back to WCF client
  throw fe;
}           
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
JL.
  • 78,954
  • 126
  • 311
  • 459