Had no luck with getting it working via config files, so decided to attempt to go the more robust route of doign it via class level attributes. If I can get this working it is clearly a great way of wrapping exceptions in Faults in the service layer withou trepeating lots of code.
However the code in the attribute never seems to get run - despite the code that defines the attribute compiling perfectly well and being recognised by the IDE. I have ran out of things to read regarding solving this - the exception just to be handled and just gets thrown.
I have also borrowed and chopped down a piece of code found on CodePlex that is on rorys site to simplify it for this problem without changing its function (removed redundant overloads)
this is driving me insane ... please help! :D
Rory Primrose - attribute implementation
Rory Primrose - IErrorHandlerImplementation
The code:
The Service interface and implementation
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(FaultException))]
string GetData(int value);
}
[ErrorHandler(typeof(KnownErrorHandler))]
public class Service1 : IService1
{
public string GetData(int value)
{
throw new Exception("This exception should get handled.");
}
}
KnownErrorHandler Implementation:
public class KnownErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
Trace.WriteLine(error.ToString());
return true;
}
public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
FaultException faultException = new FaultException("Server error encountered. All details have been logged.");
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
Attribute definition - doubt the problem is here. I am fairly sure it is in how i am using this piece of code.
[AttributeUsage(AttributeTargets.Class)]
public sealed class ErrorHandler : Attribute, IServiceBehavior
{
public ErrorHandler(Type errorHandler)
{
if (errorHandler == null)
{throw new ArgumentNullException("errorHandler");}
Type[] errorHandlerTypes = new[] { errorHandler };
Initialize(errorHandlerTypes);
}
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
// Nothing to do here
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
if (serviceHostBase == null)
{
throw new ArgumentNullException("serviceHostBase");
}
// Loop through each channel dispatcher
for (Int32 dispatcherIndex = 0; dispatcherIndex < serviceHostBase.ChannelDispatchers.Count; dispatcherIndex++)
{
// Get the dispatcher for this index and cast to the type we are after
ChannelDispatcher dispatcher = (ChannelDispatcher)serviceHostBase.ChannelDispatchers[dispatcherIndex];
// Loop through each error handler
for (Int32 typeIndex = 0; typeIndex < ErrorHandlerTypes.Count; typeIndex++)
{
Type errorHandlerType = ErrorHandlerTypes[typeIndex];
// Create a new error handler instance
IErrorHandler handler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
// Add the handler to the dispatcher
dispatcher.ErrorHandlers.Add(handler);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ }
private void Initialize(Type[] errorHandlerTypes)
{
const String ErrorHandlerTypesParameterName = "errorHandlerTypes";
if (errorHandlerTypes == null)
{
throw new ArgumentNullException(ErrorHandlerTypesParameterName);
}
if (errorHandlerTypes.Length == 0)
{
throw new ArgumentOutOfRangeException(ErrorHandlerTypesParameterName);
}
List<String> typeNames = new List<String>(errorHandlerTypes.Length);
// Loop through each item supplied
for (Int32 index = 0; index < errorHandlerTypes.Length; index++)
{
Type errorHandlerType = errorHandlerTypes[index];
// Check if the item supplied is null
if (errorHandlerType == null)
{
throw new ArgumentNullException(ErrorHandlerTypesParameterName);
}
// Check if the type doesn't define the IErrorHandler interface
if (typeof(IErrorHandler).IsAssignableFrom(errorHandlerType) == false)
{
// We can't use this type
throw new InvalidCastException();
}
String assemblyQualifiedName = errorHandlerType.AssemblyQualifiedName;
if (typeNames.Contains(assemblyQualifiedName) == false)
{
typeNames.Add(assemblyQualifiedName);
}
else
{
throw new ArgumentException(
String.Format(CultureInfo.CurrentCulture, "Duplicate ErrorType Provided", assemblyQualifiedName));
}
}
// Store the types
ErrorHandlerTypes = new ReadOnlyCollection<Type>(errorHandlerTypes);
}
/// <summary>
/// Gets the error handler types.
/// </summary>
/// <value>
/// The error handler types.
/// </value>
public ReadOnlyCollection<Type> ErrorHandlerTypes
{
get;
private set;
}
}