1

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

4

1 回答 1

0

这是实现 IErrorHandler fo 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");
                 }
            }
        }
    }
}

网络配置:

 <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 方法中,我们可以以适当的方式处理此异常。

于 2012-12-08T14:12:23.683 回答