Pages

Thursday, November 17, 2011

Modeling Client Context in WCF Web API with MEF

I am currently working on a very large-scale service-oriented enterprise application which consists of a server-side application using WCF Web API to expose a RESTful API.  There will be numerous client applications accessing the services. As part of this communication, we will be passing client context information, such as the current language, the application name, etc. in HTTP headers with each request. So, I need a way to pull this information out of the request pipeline and persist it in a way that the service code can make use of the context information PER REQUEST.

My Little MEF Problem
The simplest solution to my problem would be to create a MessageHandler that pulls the header information out, places into a context object and inserts that object into the HttpRequestMessage.Properties collection so that it is passed to the service method.  This would look something like:


    public class ClientContextMessageHandler : DelegatingHandler
    {
        public ClientContextMessageHandler()
            : base()
        {
        }
        protected override Task SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            var language = request.Headers.AcceptLanguage.First().Value;
            var context = new ClientContext()
            {
                Culture = new CultureInfo(language)
            };
            request.Properties.Add("ClientContext", context);
            return base.SendAsync(request, cancellationToken);
        }
    }


Unfortunately, I am working with a layered architecture and we use Dependency Injection to decouple our dependencies (for testing, maintainability and extensibility). We have chosen to use MEF.  This decision is part of a larger discussion but it boiled down to the fact that it is a part of the .NET Framework now, will receiving continued support from Microsoft and allows us to have dynamic composition of our API so we can easily extend the solution by simply dropping assemblies in the runtime folder.

My problem with the above solution is that I need the context information to be available throughout the application - in any layer, anywhere it's needed.  I do not want to pass the object around in every method call; therefore, I need a way to inject the object at runtime while processing a request.

I'll come back to this.

WCF Threading
I won't give a dissertation on WCF threading - mostly because I'm no expert.  But, suffice it to say, that WCF uses thread pooling and, as a result, a specific thread may be reused for multiple requests.

Why does this matter? Because any data saved in the thread, either using the [TreadStatic] attribute or a named slot, will be persisted across multiple requests.  So it is possible that data stored for one request is exposed to another. Not what we want.

However, knowing that a thread will only ever be servicing a single request at any one time should help lead us to a workable solution so long as we eliminate any risk of 'bleed through'.

Defining a Thread-Safe Context
I think I have enough information at this point to at least define my ClientContext class.  Here's what I came up with:


    internal sealed class ClientContext
        : IClientContext
    {
        [ThreadStatic()]
        private static ClientContext _instance;
        private ClientContext() { }
        public CultureInfo Culture { get; set; }
        [Export(typeof(IClientContext)]
        public static ClientContext Current
        {
            get
            {
                if (_instance == null)
                    _instance = new ClientContext();
                return _instance;
            }
        }
    }

I've essentially created a per-thread singleton that I can access through the Current property. Whenever I call ClientContext.Current, I know I will get the object for the thread I am currently executing on.

Notice that I've marked the Current property with the Export attribute. This tells MEF to use this property whenever I need to inject an instance of the IClientContext interface in my code.

Reworking the MessageHandler
Now that I have a thread-safe context, let's rework the message handler to use this class instead of instantiating a new object each time.


    public class ClientContextMessageHandler : DelegatingHandler
    {
        public ClientContextMessageHandler()
            : base()
        {
        }
        protected override Task SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            var language = request.Headers.AcceptLanguage.First().Value;
            var context = ClientContext.Current;
            context.Culture = new CultureInfo(language);
            return base.SendAsync(request, cancellationToken);
        }
    }


Notice that I am no longer storing the context in the HttpRequestMessage.Properties collection. I don't need to do this because the instance is stored in the TreadStatic variable and exposed via the MEF export.

Message Handlers vs Operation Handlers
Despite all looking good, I found the solution wasn't reliable.  Sometimes, when pumping a lot of requests into my service, the code would fail with a NullReferenceException. After some digging, I found that the Culture property was sometimes null in my service code even after setting it properly in the message hander.  I quickly learned that the message handler occassionally ran on a different thread than my service method.  Uh-oh!

Fortunately I had an opportunity to discuss this problem with Glenn Block (of Prism, MEF, WCF Web API and now Node.js fame) who was in town for a speaking engagement. It turns out that it is just a matter of making sure the context is set on the same thread the request handler (the service) is executing. The solution is to use an HttpOperationHandler instead of a MessageHandler.

According to Glenn, message handlers operate asynchronously which means they could execute on a different thread from the request handler (service) so we should never do anything in a message handler that requires thread affinity. On the other hand, operation handlers run synchronously on the same thread as the request handler, therefore we can rely on thread affinity.

Moving to an Operation Handler
So, I simple converted my message handler code to an operation handler as follows:


    internal class ClientContextOperationHandler
        : HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
    {
        public ClientContextOperationHandler()
            : base("request")
        {
        }
        protected override HttpRequestMessage OnHandle(HttpRequestMessage input)
        {
            var context = ClientContext.Current;
            var language = input.Headers.AcceptLanguage.First().Value;
            context.Culture = new CultureInfo(language);
            return input;
        }
    }


I'm not sure if I'm passing the right information to the base class constructor, but the rest of the code was a simple port from the original message handler.  I'm also using the generic base class to make the code simpler.

WTF!
So I run the application, make a test call and see that my operation handler is called as expected, the context information set but the Culture property is now always null in my service method!  What's worse is that I am able to verify that the operation handler and service method are, in fact, running on the same thread by checking the Thread.CurrentThread.ManagedThreadId value.

Coping with MEF
The problem is in how MEF satisfies the imports.  Unfortunately I don't know the details why this is the case but know how I got around it.

First, I removed the Export attribute from the Context property of my ClientContext class. Then I created the following ClientContextExporter whose sole purpose is to make MEF behave the way I want.

    [Export(typeof(IClientContext))]
    internal sealed class ClientContextExporter
        : IClientContext
    {
        public ClientContextExporter()
        {
        }
        public CultureInfo Culture
        {
            get
            {
                return ClientContext.Current.Culture;
            }
        }
    }

This type implements the same interface but delegates all members to the ClientContext.Current object. The class is marked with the Export attribute so MEF will use this class to satisfy any imports.
Wrap It Up Already!
So, that's it. I have the following types:
  • ClientContext (with the Export attribute removed) is the implementation of the context and provides the container for the thread-safe instances injected by MEF,
  • ClientContextOperationHandler plugs into the WCF Web API request pipeline to extract the header information and set the properties of the current ClientContext object.
  • ClientContextExporter simply delegates to ClientContext.Current and is the export used by MEF to satisfy any imports.
If someone have a better solution, please share!

Wednesday, October 12, 2011

We Need Better Messaging Terminology

I am current working in an enterprise environment on a solution that involves multiple Silverlight applications running on multiple systems in a client-server environment.  (To clarify, there can be multiple Silverlight applications running on a single system and there are several such systems on the network.)  The topic of messaging has been prevalent lately and I see a lot of confusion when discussing the various types of messaging.  It would make these discussions so much easier if we had common yet unique terminology for each type.

As I see it, we have the following types of messaging (along with the terminology I use to keep 'em straight!):

Inner-Application Messaging  One of the (sub-)patterns promoted by the MVVM pattern widely used for Silverlight applications is that of a Messenger.  This is also known as Broker or Event Aggregator depending on the framework you are using.  Regardless of the name, this is a way of using loosely-coupled messages to communicate between objects (view models in MVVM) rather than tightly-coupled events.  This type of messaging only pertains to communication within an application.

I refer to inner-application messaging as simply, "messaging".

Inter-Application Messaging  I actually prefer the term Notification for the next type of messaging, but as the world of mobile devices has taken off, this term has become synonymous with inter-application communication.  With Silverlight 4, Microsoft introduced a form of Silverlight client-to-Silverlight client communication using the LocalMessageSender and LocalMessageReceiver classes as well as a way to display a cute little popup window when a message is received using the NotificationWindow class.  Other examples are sending Toast notifications in Windows Phone 7.

I've been calling inter-application messaging, "notifications".

Inter-Machine Messaging  In my environment, we have a broadcasting system that runs on the server and pushes messages out to the client applications running on any machine in the network. I used to refer to this as a Notification Service keeping in line with such commercial products as SQL Server Notification Services.  However, since we don't have a better name for inter-application messaging and notifications seem to be so popular there, a new term is called for.

I've started using "broadcasting" for inter-machine messaging.

By no means am I suggesting that my terminology is the best.  In fact, quite the opposite and I solicit anyone that stumbles across this post to share your opinions.  It has truly been difficult to sit in meetings and keep everyone on the same page when discussing messaging.  We really need some standard terminology.

Sunday, September 11, 2011

Remembering 9/11

As you can see, it's been quite a while since I've blogged. I thought the 10th anniversary of the 9/11 attacks was a great time to rekindle my blog.

Today is a somber day for those of us that lived through the attacks.  I, fortunately, was not directly affected and can only imagine what life has been like for those that were.  We, like most of the country, sat in awe as the images from New York, Pennsylvania and Washington D.C. streamed across the tv and felt the fear and uncertainty what would come next.  I can still remember sitting at my desk, listening as the morning radio show crew learned of the attacks, turning the volume up as everyone in  the office huddled around and trying to use the web to find out more.

The web was still just a toddler in those days so information was difficult to track down.  We were able to see still images on the CNN site to drive home the description we were hearing on the radio.  Information was scattered and all over the map in those early hours and days.  None of us could fathom the magnitude of what was taking place or what would follow.

My kids were all young on 9/11/01.  Too young to really understand what had happened other than the fact that something had happened.  Because of this, my wife and I decided nine years ago to buy the 9/11 DVD made by Jules and Gegeon Naudet.  If you haven't watched this documentary, I suggest getting a copy.  I've yet to see a more compelling, truthful and downright riviting source of information on that day.  We watched it once and put it on the shelf.

Today my kids are 22, 20, 19, 18 and 14.  They are finally old enough to fully understand the events that day and I can think of nothing better than to remember and honor all of those that lost their lives that day then to bring my family together, significant others included, and watch the dvd once again.  We will have a nice dinner then gather in the family room to relive that day.  I'm sure we will spend a couple of hours afterwards answering questions and talking about the days that followed.

The bottom line is that we remember.  And after today my children will have a deeper understanding of a day that truly changed the world we all live in.

Peace.