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

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.

Related

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.

Objects returned from WCF service have no properties, only 'ExtentionData'

Im am not new to WCF web services but there has been a couple of years since the last time I used one. I am certain that last time I used a WCF service you could determine the type of object returned from a service call when developing the code. EG;
MyService.Models.ServiceSideObjects.User user = myServiceClient.GetUser();
You were then free to use the 'user' object client-side. However now it seems as if the WCF service will not return anything more than objects containing basic value types (string, int ect). So far I have remedied this by defining transfer objects which contain only these basic value types and having the service map the complex 'User' objects properties to simple strings and int's in the transfer object.
This becomes a real pain when, for example you have custom type objects containing more complex objects such as my Ticket object.
public class Ticket
{
public Agent TicketAgent {get;set;}
public Client Owner {get;set;}
public PendingReason TicketPendingReason {get;set;}
}
As simply mapping this object graph to a single transfer class with a huge list of inter-related system-typed properties gives a very 'dirty' client-side business model. Am I wrong in thinking that I SHOULD be able to just receive my Ticket object from a service method call and deal with it client side in the same state it was server-side ?
I realise this is probably a violation of some SoA principal or similar but my desktop app currently consuming this service is the ONLY thing that will consume ever consume it. So i do not care if many other clients will be able to manage the data types coming back from the service and therefore require some hugely normalised return object. I just want my service to get an object of type Ticket from its repository, return this object to the client with all its properties intact. Currently all I get is an object with a single property 'ExtentionData' which is unusable client-side.
Hope this makes sense, thank you for your time.
I might've missed a memo, but I think you need to decorate your model classes with DataContractAttribute and your properties with DataMemberAttribute, like so:
[DataContract( Namespace = "http://example.com" )]
public class Ticket
{
[DataMember]
public Agent TicketAgent { get; set; }
[DataMember]
public Client Owner { get; set; }
[DataMember]
public PendingReason TicketPendingReason { get; set; }
}
This is why you probably want to set up a DTO layer, to avoid polluting your model classes.
As for ExtensionData, it's used for forward-compatibility: http://msdn.microsoft.com/en-us/library/ms731083.aspx
I have marked Niklas's response as an answer as it has solved my issue.
While it seems you do not NEED to use [DataContract] and [DataMember], in some cases, I believe it could cause the issues I was experiencing. When simply transferring custom typed objects which, in themselves, only have simply typed properties, no attributes needed. However, when I attempted to transfer a custom typed object which itself had collections / fields of more custom typed objects there attributes were needed.
Thank you for your time.

WCF/WebService: Interoperable exception handling

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.

Passing Validation exceptions via WCF REST

I am using WCF and REST, and I have complex types, which are working fine. Now I need to check for validation, I am thinking of using DataAnnotations e.g.
public class Customer
{
[Required]
public string FirstName {get;set;}
}
Now where the issue is how do I pass this validation down to the REST service?
ALso I need to validate the object when it comes back, and throw an exception, if I am to throw an exception then what is the best way of doing this using REST?
I would use the Validation Application Block included in the Microsoft Enterprise Library to validate the data transfer objects being used in the service interface. You can use attributes to decorate the objects' properties with validation rules, much in the same way as with the ASP.NET Data Annotations.
In case validation fails you should return an appropriate HTTP Error Code and include the details of what went wrong in the HTTP response.
Here is an example:
public void PostCustomer(Customer instance)
{
ValidationResults results = Validation.Validate(instance);
if (!results.IsValid)
{
string[] errors = results
.Select(r => r.Message)
.ToArray();
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
WebOperationContext.Current.OutgoingResponse.StatusDescription = String.Concat(errors);
}
// Proceed with custom logic
}
If you are using the WCF REST Starter Kit, you should instead throw a WebProtocolException, as described in this article.
I would look into writing a custom IDispatchMessageInspector implementation where, in the AfterReceiveRequest method, you manually invoke the validation architecture.
I won't go into the details of how to call the Data Annotations validation architecture as I'm sure you can find that somewhere online if you don't already know how to do it. That said, once you have your validation results you can enumerate them and then, if there are any failed validations, you can throw a generic validation fault filled with the details from the AfterReceiveRequest implementation.

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)