How to fix 'System.ServiceModel.Channels.ReceivedFault' cannot be serialized - wcf

I have a workflow service. I also use workflow persistence in that service. But after I deployed workflow in IIS, from client I make a request to workflow service, in log file on server. I see a message
The execution of the InstancePersistenceCommand named {urn:schemas-microsoft-com:System.Activities.Persistence/command}SaveWorkflow was interrupted by an error.InnerException Message: Type 'System.ServiceModel.Channels.ReceivedFault' cannot be serialized.
Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.
If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
I tried research about this exception, but I didn't find anything.
How to fix this problem ? or let me know what is the reason about above exception ?

System.ServiceModel.Channels.ReceivedFault is a non-serializable internal .NET framework class, so unfortunately there is nothing you can do to correct the actual root cause (i.e. making said class serializable).
You are probably calling an external service via WCF which faults, i.e. a System.ServiceModel.FaultException is thrown. IIRC, somewhere deep down in that FaultException object is a reference to the culprit, a ReceivedFault instance.
Solution: Catch all FaultExceptions, transfer the information you need to know from the FaultException into a serializable exception, and throw the latter:
try
{
CallService();
}
catch (FaultException ex)
{
// Gather all info you need from the FaultException
// and transport it in a serializable exception type.
// I'm just using Exception and the message as an example.
throw new Exception(ex.Message);
}

Related

Is it possible to configure a WCF service client to throw a custom FaultException?

I was wondering if it was possible to configure a WCF service client to use a custom type instead of FaultException when throwing faults. The custom type would inherit from FaultException, but also have some additional details about the error.
The reason I want to use a custom FaultException is so I can store a GUID from the SOAP Header which is otherwise lost.
I know I could manually catch and rethrow any faults my service client returns, but that's flimsy. I have no way of guaranteeing future developers will do the same.
I've thought about subclassing the generated service client class and putting the error handling in there, but that generates a lot of work whenever the target service changes.
So, is it possible to configure a WCF service client to throw a custom FaultException type for Faults?
You can create your own IErrorHandler implementation:
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx
Override ProvideFault and then do conversion from regular exceptions (including plain FaultException) to your own custom based FaultException<T>, where T is your own type that you can define to include custom properties.
After that, you have to register your implementation of IErrorHandler as service behavior, either in code or in web/app config.

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 FaultException Without Sending StackTrace

I have some WCF services with predefined FaultContract attributes. When the FaultException<TDetail> exceptions are thrown, they're sending StackTrace, Source and other potentially unsave information.
Is it possible to return only:
Detail (from the generic TDetail)
FaultMessage
FaultCode
(and possibly) FaultReason
Have you tried rolling your own fault exception using IErrorHandler? Also make sure in your app config file, the IncludeExceptionDetailInFaults attribute is set to false and, this might be helpful for best pratices.

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;
}