如何使用自定义筛选器更改WCF路由器备份列表行为?

时间:2012-08-19 03:06:22

标签: wcf wcf-routing

我正试图找到一种方法来处理WCF路由器中的异常,这意味着什么时候路由器无法向主端点发送消息(这里有EndpointNotFoundException,ServerTooBusyException或CommunicationObjectFaultedException)并且选择一个端点从备份列表中将此消息发送到备份端点。如何在路由器服务中获得此内部异常?因为此时我想在内存中动态更改路由器配置,并使用主端点更改备份端点。是否可以使用IErrorHandler执行此操作?或者是否可以执行此自定义筛选?如何使用自定义过滤器更改备份行为?

1 个答案:

答案 0 :(得分:0)

这是一个完整的工作示例,用于实现IErrorHandler和wcf服务。我们可以为WCF路由器实现这一点并在路由器级别获取内部异常,然后决定如何在运行时更改配置。

[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>

所以在HandleError方法中我们可以正确处理这个异常。