WCF/WebService: Interoperable exception handling - wcf

I understand that WCF will convert an exception into a fault and send it back as a SOAP message, but I was wondering if this is truly interoperable. I guess I'm having a tough time trying to figure out this possible scenario:
Client (Java) calls a WCF Service
(LoginService).
Server checks for proper authorization, user authorization fails.
Server throws an UnauthorizedAccessException.
WCF converts this into a Fault somehow. (* - See Below As Well)
Client has to be able to know how to read this Fault.
I guess I'm just having a tough time understanding how this could still be interoperable because it is expecting Java to know how to translate a SOAP Fault that .NET encodes from an UnauthorizedAccessException.
Also, how does .NET actually convert the exception to a fault, what goes in as the fault code, name, etc. Some of the things seem to be "duh"s like perhaps the Fault Name is "UnauthorizedAccessException", but I'd rather know for sure than guess.

There is no "automatic conversion". WCF will return a fault (I forget which one) when you have an unhandled exception. But since you didn't declare that fault, many, if not most, clients will fail if you return it.
You are meant to define your own faults and to return them instead. Consider:
[DataContract]
public class MySpecialFault
{
public string MyMessage { get; set; }
}
[ServiceContract]
public interface IMyService
{
[FaultContract(typeof (MySpecialFault))]
[OperationContract]
void MyOperation();
}
public class MyService : IMyService
{
public void MyOperation()
{
try
{
// Do something interesting
}
catch (SomeExpectedException ex)
{
throw new FaultException<MySpecialFault>(
new MySpecialFault {MyMessage = String.Format("Sorry, but {0}", ex.Message)});
}
}
}
Any client capable of handling faults will deal with this. The WSDL will define the fault, and they will see a fault with the Detail element containing a serialized version of the MySpecialFault instance that was sent. They'll be able to read all the properties of that instance.

Faults have been part of the SOAP specification since v1.1. They are explained in the SOAP Specification.
It is up to implementations (WCF, Java etc) to ensure that Faults are handled according to the specification.
Since WCF converts FaultExceptions to Faults according to the SOAP specification, FaultExceptions thrown from WCF are interoperable.

SOAP faults are interoperable but .Net exception classes are not good to be used in SOAP faults. Instead define your own DataContract class (e.g. AccessFault) and then use it in a FaultContract.
see http://msdn.microsoft.com/en-us/library/ms733841.aspx
Whenever there is a UnauthorizedAccessException thrown at service boundary convert it to FaultException.
This can be done in several ways like using Microsoft Enterprise Library Exception Handling Block or implementing the IErrorHandler interface.

Related

How client application comes to know that a particular wcf method throws faultexception or not?

I know a wcf method throws fault exception and client application catches that fault exception. But is there any way to know that whether that wcf method throws fault exception or not at client side ?
When you create a WCF service you could decorate your operation contract with the [FaultContract] attribute:
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(MyFaultContract))]
void DoWork();
}
This emits information about this MyFaultContract in the metadata (WSDL) of the service. Then when you create a client proxy (either using the Add Service Reference in VS or directly by the svcutil.exe) this fault contract is known by the client and you can catch exceptions of this type.
So the idea here is to look whether your operation contract is decorated with the [FaultContract] attribute to know which type of fault contracts this operation might throw. If it hasn't any custom FaultContract attributes defined on it it means that on the client you can catch only for the non-generic version of the FaultException.

WCF newbie - is FaultException<T> safe for non-.NET clients?

WCF Newbie alert. I'm reading "Learning WCF" and "Programming WCF Services" where both books recommend throwing FaultException<T>. If T is .NET type "DivideByZeroException" and assuming a FaultContract exists with
[FaultContract(typeof(DivideByZeroException))]
on method "Divide", will a non-.NET client consuming that WCF service and method be able to understand and process that .NET exception? If yes, is it because the type info (DivideByZeroException) is part of the metadata (because of the FaultContract) that the client has access to and uses?
Thanks for any help.
You can throw a FaultContract<DivideByZeroException>, but in general you shouldn't do that, exactly for the reason you mentioned (*). What is usually recommended is to have a data contract with the information from the exception, such as the exception message, and then have a FaultContract of that type.
[DataContract]
public class MyErrorDetails
{
[DataMember]
public string ErrorCode { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
}
And then use
[FaultContract(typeof(MyErrorDetails))]
(*) Another reason to avoid returning exceptions as faults is that they disclose more information to the client than the client needs; things such as the stack trace are serialized by the exception, but that's some information internal to the service and shouldn't be sent to clients.

Better Practice for Error handling from WCF

I have a class library that communicates with my WCF service. The class library can then be used in any of my applications. I am curious as to what would be the best practice in handling the errors. I have thought of two scenarios but wanted to get some feedback from the community. The idea is not only to make sure it's appropriate for .NET solutions, but any other language that might not use the dll but rather call the service directly via a SOAP style call.
Option #1
Create a result object which will return to the caller API. Such as.
Public abstract BaseResponse
{
[DataMember]
Public bool IsSuccess { get; set;}
[DataMember]
Public string ErrorMsg { get ;set ;}
}
Public GetProductResponse : BaseResponse
{
[DataMember]
Public Product p { get;set;}
}
Option #2 : Throw a SOA Fault and allow the end user handle it however they choose. I could handle it in my API - however a direct call to the service would require that end user to code against the fault and handle it correctly.
Typically what I end up doing is having a business layer that will throw application specific exceptions. In the event that I want to expose this as a web service, I'll put a very thin layer on top of that that exposes those business services as WCF services. This layer will do nothing more than pass calls down to the business layer and return results as DataContract or MessageContract objects. In this very thin WCF layer, I'll catch exceptions from the business layer and map them to SOAP faults. This allows any .Net application to consume the business layer directly and catch exceptions as well as .Net or non-.Net applications to consume the web service and catch SOAP faults.
I usually use Option 2 (soap faults, WCF FaultContracts) then I am doing an internal service, where I know the client is also WCF, and I can make sure FaultExceptions are handled correctly.
When I am making an external/customer-facing service, I usually use option 1, splitting up my message into a "header" and a "body" and have the header contain an error message. I find this easier for other people to understand when telling them how to use your web service, and easier for non-WCF users to implement.
Both ways are fine really, as any decent SOAP tool for whatever language should handle SOAP faults, but you never know...
If you are building a restful webservice yo could use the http status code. And regardless of the service flavour the error handlers in WCF makes the code substantially more readable since it allows a single try/catch definition for methods.
There is a simple example here http://bit.ly/sCybDO
I would use option #2 every time. Faults are a standardised part of the SOAP specification, so any compliant framework should handle them appropriately. If a client is using a framework that doesn't have built in handling, then they will have to write custom code to do it, but that is the case with option #1 anyway, since they will have to understand your custom error semantics.
Unless there is a really good reason, I would always used the standardised approach - it give you the best chance of interoperability.

WCF - Catching faults on the server and returning custom types instead

We are trying to figure out a way to modify WCF service behavior to catch all exceptions and instead of returning faults to the client, it will populate a custom return object with exception data and return that. So far, we haven't had much luck. I found this example: Catching custom faults
However, it doesn't return custom types as we would like it to. What other options are there?
Thanks!
If you want to have an interoperable and "by-the-standard" service, you should always return FaultException<T> SOAP faults from your service to the client.
Since that type takes a generic <T>, you can basically put anything into that type there to report back your errors. That type needs to be decorated with a [DataContract], and its members that need to be passed back with [DataMember] attributes.
[DataContract]
public class MyErrorInfo
{
[DataMember]
public int ErrorCode { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
}
When you catch those execptions on the service side and return a FaultException<MyErrorInfo> (or whatever you'll end up calling your error class), you also need to decorate your operations with a
[FaultContract(typeof(MyErrorInfo))]
[OperationContract]
public SomeType SomeMethodCall(SomeType parameter);
so that your clients will be able to catch the FaultException<MyErrorInfo> and handle it.
I referred to this article in another answer, but it may help you as well..
WCF Exception Handling
the article is Simplifying WCF: Using Exceptions as Faults
I wrote a blog post on this exact topic after we encountered this in our own project. Basically, we chose to return the same object type so we can attach a single listener delegate to all events to globally handle certain errors (like a user losing the permissions to an org.)
I hadn't thought of using FaultException but I will examine how we might do that. This design was WCF Service (.NET 3.5) running inside SharePoint 2007 and consumed by Silverlight 4.

What is the best approach to handle exceptions in WCF service?

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:
Invalid URL
WCF service is down
SQL server 2005 is not running
Client is not on the same domain
Authentication fails
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.
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:
Rory Primrose: Implementing IErrorHandler
Useful WCF behaviors: IErrorHandler
Create a custom fault class that is marked with the DataContract attribute
Mark the method on the service contract interface with FaultContract. Ie. [FaultContract(typeof(CustomFault))]
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);
}
}
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.
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;
}