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服务端创建消息检查器,请使用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)中发送一个自定义头。
测试代码:
- 创建Windows控制台应用程序
- 插入代码(每个块在一个类)
- 运行程序
- 使用浏览器打开url:
http://localhost:9001/Message/Test
- 响应是一个Json:{"消息":"好的!","成功":真正}
- 您可以检查响应和查看自定义头:"user-agent:My Browser"
您只使用ApplyClientBehavior
将消息检查器放在客户端。服务端还有另一个方法:
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
if (endpointDispatcher != null)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageInspector());
}
}