WCF 文化信息传递实现

在当前的项目中,使用WCF来实现从互联网客户端到 Windows 服务的通信。WCF 能够自动地让 Windows 身份验证信息从客户端流向服务器,这非常便利。然而,客户端的文化信息(例如语言和地区设置)并没有被传递,这导致在读取本地化数据(例如资源文件)时,应用无法透明地处理本地化。本文将展示如何通过实现自定义的 WCF 消息检查器(MessageInspector)来解决这个问题。

这种扩展只应在控制通信两端(客户端和服务器)的情况下使用。如果只创建服务器并关心互操作性,最好使用更标准的方法,如 Pablo Cibraro 在《WCF的全球化模式(WS-I18N 实现)》中描述的那样。

使用代码

解决方案分为四个项目:服务器、客户端、扩展和服务接口。其中,扩展项目是最有趣的部分。在示例中,客户端设置了当前线程的文化信息,并调用服务器上的一个简单的 "Hello World" 方法。服务器响应时,输出当前线程的文化信息。

这是自定义的消息检查器,其中客户端的 BeforeSendRequest 方法添加了包含线程文化信息的消息头,服务器端的 AfterReceiveRequest 方法提取自定义消息头并设置当前执行线程的文化信息。

public class CultureMessageInspector : IClientMessageInspector, IDispatchMessageInspector { private const string HeaderKey = "culture"; public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { request.Headers.Add(MessageHeader.CreateHeader(HeaderKey, string.Empty, Thread.CurrentThread.CurrentUICulture.Name)); return null; } public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) { int headerIndex = request.Headers.FindHeader(HeaderKey, string.Empty); if (headerIndex != -1) { Thread.CurrentThread.CurrentUICulture = new CultureInfo(request.Headers.GetHeader(headerIndex)); } return null; } }

自定义行为的创建如下:

public class CultureBehaviour : IEndpointBehavior { public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new CultureMessageInspector()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CultureMessageInspector()); } }

创建 ServiceHost 时,将自定义行为添加到 ServiceEndPoint 的行为集合中。这也可以配置在配置文件中。

Server server = new Server(); ServiceHost host = new ServiceHost(server, new Uri("net.tcp://localhost:8080")); NetTcpBinding binding = new NetTcpBinding(); ServiceEndpoint endPoint = host.AddServiceEndpoint(typeof(IHelloWorld), binding, "Server"); endPoint.Behaviors.Add(new CultureBehaviour());

创建客户端通道时,也将自定义行为添加到 ServiceEndPoint 的行为集合中。这也可以配置在配置文件中。

ServiceEndpoint tcpEndPoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IHelloWorld)), new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:8080/server")); ChannelFactory factory = new ChannelFactory(tcpEndPoint); factory.Endpoint.Behaviors.Add(new CultureBehaviour()); return factory.CreateChannel();

关注点

不确定运行 AfterReceiveRequest 的线程是否与运行实际服务器代码的线程相同。在这种情况下,它们是相同的。如果需要在 WCF 管道的其他部分使用消息头中的数据,应该将数据添加到请求的属性集合中。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485