The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
To prevent the Server from fall in Fault state, you have to ensure that no unhandled exception is raised. If WCF sees an unexpected Exception, no more calls are accepted - safety first.
Two possibilties to avoid this behaviour:
Use a FaultException (this one is not unexpected for WCF, so the WCF knows that the server has still a valid state)
instead of
throw new Exception("Error xy in my function")
use always
throw new FaultException("Error xy in my function")
perhaps you can try..catch the whole block and throw a FaultException in all cases of an Exception
try
{
... some code here
}
catch (Exception ex)
{
throw new FaultException(ex.Message)
}
Tell WCF to handle all Exceptions using an Errorhandler. This can be done in several ways, I chose a simple one using an Attribute:
All we have to do more, is to use the attribute [SvcErrorHandlerBehaviour]
on the wanted Service Implementation
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace MainService.Services
{
///
/// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
///
public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ } //implementation not needed
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints,
BindingParameterCollection bindingParameters)
{ } //implementation not needed
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
if (channelDispatcher == null)
continue;
channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
}
}
}
public class SvcErrorHandler: IErrorHandler
{
public bool HandleError(Exception error)
{
//You can log th message if you want.
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
if (error is FaultException)
return;
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
msg = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
}
This is an easy example, you can dive deeper into IErrorhandler by not using the naked FaultException
, but a FaultException<>
with a type that provides additional info
see IErrorHandler for an detailed example.