I have some WCF services using dataContracts and i wanted to I was hoping to pass a Exception with custom Dictionary< string , object > data in the Data property, but when i add any data on this array before throwing i get the following error in the ErrorHandler of my custom ServiceBehavior:
Type 'System.Collections.ListDictionaryInternal'
with data contract name 'ArrayOfKeyValueOfanyTypeanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Do i invariably need to create a custom exception with a Dictionary property annotated as a DataContract and throw that? the idea of using the ErrorHandler is avoiding to handle exceptions in each service method, do i still need to add further annotations to the methods? what i am missing?
for reference, this is my FaultErrorHandler class:
public class FaultErrorHandler : BehaviorExtensionElement, IErrorHandler, IServiceBehavior
{
public bool HandleError(Exception error)
{
if (!Logger.IsLoggingEnabled()) return true;
var logEntry = new LogEntry
{
EventId = 100,
Severity = TraceEventType.Error,
Priority = 1,
Title = "WCF Failure",
Message = string.Format("Error occurred: {0}", error)
};
logEntry.Categories.Add("MiddleTier");
Logger.Write(logEntry);
return true;
}
public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
var faultException = new FaultException<Exception>( error, new FaultReason(string.Format("System error occurred, exception: {0}", error)));
var faultMessage = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, faultMessage, Schema.WebServiceStandard);
}
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers)
{
chanDisp.ErrorHandlers.Add(this);
};
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
public override Type BehaviorType
{
get { return typeof(FaultErrorHandler); }
}
protected override object CreateBehavior()
{
return new FaultErrorHandler();
}
}
my typical service interface looks like:
[ServiceContract(Name = "Service", Namespace = Schema.WebServiceStandard, SessionMode = SessionMode.Allowed)]
public interface IService
{
[OperationContract(Name = "GetSomething")]
[FaultContract(typeof(ValidationFault))]
LookupResult GetSomething();
}