Cookies and the Silverlight client HTTP stack

In Silverlight 3 and newer versions you can choose between the browser HTTP stack and the client HTTP stack. The choice between them is an important one to make since you get or loose features when you switch from the browser HTTP stack to the client HTTP stack and vice versa.

In this article I’m not going into much detail how and when to make this choice but rather I like to explain how you can overcome a specific problem with cookies when you’re using the client HTTP stack. So what’s the problem then? The problem with the client HTTP stack is that you don’t have support for HTTP cookies. To get support for HTTP cookies you need to write a custom behavior and inject it when creating a new client proxy instance to communicate with the server.

How to add support for cookies

Adding support for cookies to the client HTTP stack in Silverlight is done by implementing a custom message inspector that configures a cookie container for each request send to the server. When you look at it in term of schematics it looks like the image displayed below.

image

The cookie container is shared between the various clients that use the behavior so that you don’t need to manage a separate cookie container for each instance created. This is essential when using this behavior for cookie based authentication scenario’s. If you don’t keep the cookie container you will have to authenticate the client with each call. Doing that doesn’t help the performance of your client.

Creating a CookieBehavior class

The cookie endpoint behavior class is responsible for injecting a special message inspector into the WCF client runtime of Silverlight. The code for the behavior is displayed below:

public class CookieBehavior: IEndpointBehavior
{

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
            
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
        // Bind the cookie message inspector to the client runtime
        clientRuntime.MessageInspectors.Add(new CookieClientMessageInspector());
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
            
    }

    public void Validate(ServiceEndpoint endpoint)
    {
            
    }
}

Creating the message inspector

When the client is started a new message inspector is injected into the client runtime by the endpoint behavior described in the previous section. The message inspector itself is responsible for actually configuring the cookie container before a request is send to the server. The code for the message inspector is displayed below.

public class CookieClientMessageInspector : IClientMessageInspector
{
    // Use a static cookie container so that all client proxy instances share the same cookies
    private static readonly CookieContainer _cookieContainer = new CookieContainer();

    public CookieClientMessageInspector()
    {
            
    }

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {

    }

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
    {
        // Bind the cookie container from the message inspector to the channel
        var _cookieManager = channel.GetProperty<IHttpCookieContainerManager>();

        if (_cookieManager != null)
        {
            _cookieManager.CookieContainer = _cookieContainer;
        }
            
        return null;
    }
}

There’s no need to extract the cookie container from  the response when it is received from the server. The WCF runtime will reuse the cookie container configured when the request was send in the response to save the cookies send to the client by the server.

Final words

Fixing the cookie problem for the client HTTP stack is pretty straightforward. The sample code is included as an attachment to this post.

One final word of warning: The server code uses ASP.NET compatibility mode to extract and set the cookie information. There are better ways to do this, by applying a similar cookie behavior to the server. Remember, this is demo code Winking smile

Cheers!