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
Fault exception in WCF. It is used in a client application to catch contractually-specified SOAP faults. By the simple exception message, you can't identify the reason of the exception, that's why a Fault Exception is useful.
In a WCF service, if it throws an exception inside the service, the client will not get the details. In order to get the formatted exception details on client side, you need to use FaultException instead to let the client know the details. The FaultException information can be serialized as expected.
Using FaultExceptionFault exceptions are exceptions that are thrown by a WCF service when an exception occurs at runtime -- such exceptions are typically used to transmit untyped fault data to the service consumers.
Exceptions are used to communicate errors locally within the service or the client implementation. Faults, on the other hand, are used to communicate errors across service boundaries, such as from the server to the client or vice versa.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With