WCF:自定义消息检查器没有被连接起来

本文关键字:连接 起来 自定义消息 检查 WCF | 更新日期: 2023-09-27 18:13:32

我已经在服务端定制了一个错误处理程序:

 public class GlobalErrorHandler : Attribute, IErrorHandler, IServiceBehavior
    {
        public void AddBindingParameters(
            ServiceDescription serviceDescription,
            ServiceHostBase serviceHostBase,
            Collection<ServiceEndpoint> endpoints,
            BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler = new GlobalErrorHandler();
            foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                if (channelDispatcher != null)
                {
                    channelDispatcher.ErrorHandlers.Add(errorHandler);
                }
            }
        }
        public bool HandleError(Exception error)
        {
            Trace.TraceError(error.ToString());
            if (error is FaultException)
                return false; // Let WCF do normal processing
            else
                return true; // Fault message is already generated
        }
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error is FaultException)
            {
                // Let WCF do normal processing
            }
            else
            {
                // Generate fault message manually
                MessageFault messageFault = MessageFault.CreateFault(
                    new FaultCode("Sender"), new FaultReason(error.Message),
                    error, new NetDataContractSerializer());
                fault = Message.CreateMessage(version, messageFault, null);
            }
        }
    }
    public class ErrorHandlerElement : BehaviorExtensionElement
    {
        protected override object CreateBehavior()
        {
            return new GlobalErrorHandler();
        }
        public override Type BehaviorType
        {
            get { return typeof (GlobalErrorHandler); }
        }
    }

我在客户端定义了一个自定义消息检查器:

public class MessageInspector : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            if (reply.IsFault)
            {
                //do some processing
            }
        }
        public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel)
        {
            return null;
        }
}

我有一个自定义行为来连接消息检查器:

public class NewtonsoftJsonBehavior : WebHttpBehavior
{
 public override void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime       clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new MessageInspector());
        }
}

,此行为通过工厂编程地应用:

public class JsonWebServiceHostFactory : WebServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            var host =  base.CreateServiceHost(serviceType, baseAddresses);
            //return host;
            //ServiceEndpoint ep = host.AddServiceEndpoint(serviceType, new WebHttpBinding(), "");
            //host.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });     
            //return host;
            WebHttpBinding webBinding = new WebHttpBinding();
            host.AddServiceEndpoint(serviceType, webBinding, "").Behaviors.Add(new NewtonsoftJsonBehavior());
            return host;
        }
    }

然而,当我调试并在服务中生成faultexception时,调用globalerrorhandler,但调试器从未进入消息检查器。知道为什么吗?

WCF:自定义消息检查器没有被连接起来

要在WCF服务端创建消息检查器,请使用IDispatchMessageInspector的实现而不是:IClientMessageInspector

一个例子:

服务:

EndpointAddress endpoint = new EndpointAddress("http://localhost:9001/Message");
WebServiceHost svcWebHost = new WebServiceHost(typeof(Service.Message), endpoint.Uri);
CustomServiceBehavior serviceBehavior = new CustomServiceBehavior();
svcWebHost.Description.Behaviors.Add(serviceBehavior);
Binding webHttpBinding = new WebHttpBinding();
ServiceEndpoint serviceEndpoint = svcWebHost.AddServiceEndpoint(typeof(Service.IMessage), webHttpBinding, endpoint.Uri);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
svcWebHost.Description.Behaviors.Add(smb);
ServiceDebugBehavior sdb = svcWebHost.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;
svcWebHost.Open();

服务合同

[ServiceContract]
public interface IMessage
{
    [OperationContract]
    [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
    Model.TestResponse Test();
}
服务实现

public class Message : IMessage
{
    public Model.TestResponse Test()
    {
        return new Model.TestResponse() { success = true, message = "OK!" };
    }
}

CustomServiceBehavior实现IServiceBehavior:

public class CustomServiceBehavior : IServiceBehavior
{
    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)
    {
        CustomEndpointBehavior endpointBehavior = new CustomEndpointBehavior();
        foreach (var endpoint in serviceDescription.Endpoints)
            endpoint.EndpointBehaviors.Add(endpointBehavior);
    }
    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }
}

CustomEndpointBehavior实现IEndpointBehavior

public class CustomEndpointBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }
    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
    }
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        var inspector = new CustomDispatchMessageInspector();
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
    }
    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

CustomDispatchMessageInspector实现IDispatchMessageInspector

public class CustomDispatchMessageInspector : IDispatchMessageInspector
{
    public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
    {
        return null;
    }
    public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {
        var httpResponse = ((HttpResponseMessageProperty)reply.Properties["httpResponse"]);
        httpResponse.Headers.Add("user-agent", "My Browser");
    }
}

这个例子是一个没有配置文件的WCF Self - hosting(在代码中配置WCF服务),它返回一个Json并在HTTP响应(user-agent:My Browser)中发送一个自定义头。

测试代码:

  1. 创建Windows控制台应用程序
  2. 插入代码(每个块在一个类)
  3. 运行程序
  4. 使用浏览器打开url:http://localhost:9001/Message/Test
  5. 响应是一个Json:{"消息":"好的!","成功":真正}
  6. 您可以检查响应和查看自定义头:"user-agent:My Browser"

您只使用ApplyClientBehavior将消息检查器放在客户端。服务端还有另一个方法:

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
  if (endpointDispatcher != null)
  {
    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageInspector());
  }
}