Click here to Skip to main content
Click here to Skip to main content

Automatic Culture Flowing with WCF by using Custom Behaviour

, 30 Nov 2007
Rate this:
Please Sign up or sign in to vote.
An article to demonstrate culture flow from Windows client to Windows server using WCF.
Screenshot - CultureServer.png

Contents

Introduction

On a project I am working on, we use WCF to communicate from an internet client to a Windows service. WCF automatically lets the windows identity flow from the client to the server. This is great but it is not the case for the culture of the client. If the culture would also flow from the client to the server reading localised data from, for example, the resource file could be completely transparent for the application. This example demonstrates how you could implement such a solution by implementing a custom WCF MessageInspector.

Background

The given extension should only be used if you are controlling both ends of the wire (client and server). If you are only creating the server and care about interop you are better off using a more standard method like the one described in Globalization Patterns in WCF (WS-I18N implementation) by Pablo Cibraro.

WCF has several extension points; in this example a custom MessageInspector is used. A custom MessageInspector can be used to inspect or modify messages as they pass through a WCF client or server object. To inspect or modify messages as they pass through a client, you should implement the IClientMessageInspector interface. To inspect or modify messages as they pass through a server, you should implement the IDispatchMessageInspector interface. The custom MessageInspector in this example implements both interfaces.

The custom MessageInspector adds a custom Message Header to the request at the client which contains the culture info of the thread running the client. At the server side, the custom MessageInspector retrieves the culture info from the custom Message Header and sets the culture info on the running thread.

To use the custom message inspector, a custom behaviour also needs to be created which implements IEndpointBehavior. This behaviour is then added to the behaviours collection of the WCF endpoint.

Using the Code

The solution is divided into four projects: the server, the client, the extension and the service interface. The interesting part is the extension project. In the example, the client sets the culture info of the current thread and calls a simple "hello world" method on the server. The server responds with a Console.Writeline with the culture of the running thread.

MessageInspector

This is the custom Message Inspector where the BeforeSendRequest at the client adds the message header and the AfterReceiveRequest at the server extracts the custom header and sets the culture of the currently executing thread.

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<string />(headerIndex));
    }
    return null;
  }
  ...

Custom Behaviour

The custom behaviour is created like this:

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());
  }
  ...

Creating the Service Host

When creating the ServiceHost, the custom behaviour is added to the behaviours collection of the ServiceEndPoint. This could also be configured in the configuration file.

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());

Creating the Client Channel

When creating the client channel, the custom behaviour is also added to the behaviours collection of the ServiceEndPoint. This could also be configured in the configuration file.

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

Points of Interest

I did not know for sure that the thread running the AfterReceiveRequest would be the same as the thread running the actual server code. In this case it was. If you need the data from the message header in another part of the WCF pipeline, you should add the data to the properties collection of the request.

After I found the right extension point, the actual implementation was simple. There are many extension points, finding the right one is the difficult part.

History

  • v1.0 27/11/2007: Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Patrick Kalkman
Architect http://www.hinttech.nl
Netherlands Netherlands
Patrick Kalkman is a senior Software Architect with more than 20 years professional development experience. He works for Hinttech where he develops state of the art web applications.

Patrick enjoys writing his blog. It discusses software architectures using semantic web technologies. Patrick can be reached at pkalkie@gmail.com.
 
Published Windows 8 apps:
 
Published Windows Phone apps:
 
Awards:

Best Mobile article of March 2012
Best Mobile article of June 2012
Follow on   Twitter

Comments and Discussions

 
QuestionInteroperability Pinmemberwiwiedbulu9-Jul-14 21:30 
QuestionHow to make it work on WCF hosted on IIS PinmemberMember 241951915-Feb-13 2:12 
Questionunable to invoke the AfterReceiveRequest method Pinmemberdoe joh16-Aug-12 14:08 
AnswerRe: unable to invoke the AfterReceiveRequest method PinmemberPatrick Kalkman8-Oct-12 22:03 
QuestionCan get this code to work with service hosted by iis Pinmemberdoe joh16-Aug-12 11:10 
AnswerRe: Can get this code to work with service hosted by iis PinmemberPatrick Kalkman8-Oct-12 22:04 
QuestionThanks Pinmemberdoe joh14-Aug-12 14:25 
AnswerRe: Thanks PinmemberPatrick Kalkman14-Aug-12 23:04 
GeneralBehaviourExtension PinmemberBlueLeaf7-May-09 10:33 
GeneralRe: BehaviourExtension PinmemberPatrick Kalkman1-Mar-11 2:55 
Thank you.
GeneralGood job PinmemberMember 36886039-Dec-08 22:27 
GeneralRe: Good job PinmemberPatrick Kalkman1-Mar-11 2:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 30 Nov 2007
Article Copyright 2007 by Patrick Kalkman
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid