How can I change the WCF Router Backup List Behavior with Custom Filter?

626 views Asked by At

I'm trying to find a way to handle exception in WCF router, it means when for any reason router can not send message to primary endpoint (here, there is EndpointNotFoundException, ServerTooBusyException, or CommunicationObjectFaultedException) and goes and select an endpoint from backup list and send this message to backup endpoint. how can I get this internal exception in router service? because at this time I want to change the router configuration dynamically in memory and change the backup endpoint with primary endpoint. is it possible to do this with IErrorHandler? or is it possible to do this Custom Filter ? How I can change the backup behavior with Custom Filter?

1

There are 1 answers

0
Morteza Azizi On BEST ANSWER

this is a full working example to implement IErrorHandler fo wcf service. we can implement this for WCF Router and get the internal exception in router level and then make decision how we can change the configuration in the runtime.

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(MyFault))]
    string GetData(int value);
}

[DataContract]
public class MyFault
{

}

public class Service1 : IService1
{
    public string GetData(int value)
    {
        throw new Exception("error");
    }
}

public class MyErrorHandler : IErrorHandler
{
     public bool HandleError(Exception error)
     {
         return true;
     }

     public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
     {
         var vfc = new MyFault();
         var fe = new FaultException<MyFault>(vfc);
         var fault = fe.CreateMessageFault();
         msg = Message.CreateMessage(version, fault, "http://ns");
     }
}

public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior
{
     public override Type BehaviorType
     {
         get { return GetType(); }
     }

     protected override object CreateBehavior()
     {
         return this;
     }

     private IErrorHandler GetInstance()
     {
         return new MyErrorHandler();
     }

     void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription,      ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {

    }

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        IErrorHandler errorHandlerInstance = GetInstance();
        foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            dispatcher.ErrorHandlers.Add(errorHandlerInstance);
        }
    }

    void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
        {
            if (endpoint.Contract.Name.Equals("IMetadataExchange") &&         endpoint.Contract.Namespace.Equals("http://schemas.microsoft.com/2006/04/mex"))
                continue;

            foreach (OperationDescription description in endpoint.Contract.Operations)
            {
                 if (description.Faults.Count == 0)
                 {
                     throw new InvalidOperationException("FaultContractAttribute not found on this method");
                 }
            }
        }
    }
}

web.config:

 <system.serviceModel>
     <services>
         <service name="ToDD.Service1">
             <endpoint address="" binding="basicHttpBinding" contract="ToDD.IService1" />
         </service>
     </services>

     <behaviors>
         <serviceBehaviors>
             <behavior>
                 <serviceMetadata httpGetEnabled="true"/>
                 <serviceDebug includeExceptionDetailInFaults="false"/>
                 <errorHandler />
             </behavior>
         </serviceBehaviors>
     </behaviors>

     <extensions>
         <behaviorExtensions>
             <add name="errorHandler" type="ToDD.ErrorHandlerExtension, ToDD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
         </behaviorExtensions>
     </extensions>
</system.serviceModel>

so in HandleError method we can handle this exception in proper way.