Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Send Cookies When Making WCF Service Calls

4.79/5 (11 votes)
3 May 2011CPOL4 min read 89.6K   1.3K  
This article presents an example on how to send cookies when making WCF service calls.

Introduction

This article presents an example on how to send cookies when making WCF service calls.

Background

Once in a while, you may find that you want to send some information in the form of "Cookies" to the server when making WCF calls. For example, if the WCF service is protected by a "Forms Authentication" mechanism, you will need to send the authentication cookie when making the WCF call to gain the required access to the service.

  • If you are calling a "REST" service using the "WebClient" class, this should not be a difficult task. You can simply work on the "CookieContainer" property of the "HttpWebRequest" class.
  • If you are calling a regular WCF service, and your client proxies are generated by the "Adding service reference" tool in the Visual Studio, the method to send cookies is not so obvious.

This article is to present an example on how to send cookies when making WCF calls using the Visual Studio generated client proxies.

SolutionExplorer.JPG

The attached Visual Studio solution is developed in Visual Studio 2010. It has two projects:

  • The "WCFHost" is a simple ASP.NET MVC project that hosts the example WCF service.
  • The "WCFClient" is a simple WPF project. I will show you how to send cookies when calling WCF services in this project.

Let us start by first taking a look at the WCF service.

The WCF Service

The example WCF service is implemented in the "ServiceWithCookies.svc.cs" file in the "WCFHost" project.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Web;
using System.ServiceModel.Activation;
 
namespace WCFHost
{
    [DataContract]
    public class CookieInformation
    {
        [DataMember(Order = 0)]
        public string Key { get; set; }
        [DataMember(Order = 1)]
        public string Value { get; set; }
    }
 
    [ServiceContract]
    public interface IServiceWithCookies
    {
        [OperationContract]
        CookieInformation EchoCookieInformation();
    }
 
    [AspNetCompatibilityRequirements(RequirementsMode
        = AspNetCompatibilityRequirementsMode.Required)]
    public class ServiceWithCookies : IServiceWithCookies
    {
        public CookieInformation EchoCookieInformation()
        {
            var request = HttpContext.Current.Request;
            string key = "NA";
            string value = "NA";
 
            if (request.Cookies.Count > 0)
            {
                key = request.Cookies.Keys[0];
                value = request.Cookies[key].Value;
            }
 
            return new CookieInformation()
            {
                Key = key,
                Value = value
            };
        }
    }
}
  • The "DataContract" "CookieInformation" class has two fields named "Key" and "Value".
  • The implementation of the "OperationContract" "EchoCookieInformation" reads the cookie from the client and puts the information into an instance of the "CookieInformation" class.

Sending application data to WCF services by cookies is not the "recommended" way of communicating business data. In this example, the whole purpose of reading the cookie from the client is to show you that the WCF client can indeed send cookies to the server. In order that the WCF service method "EchoCookieInformation" has access to the "HttpContext", we need to add the following in the "web.config" file inside the "<system.serviceModel>" tag.

XML
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

Now we can take a look at how the client sends cookies when making the call.

The WCF Service Client

In order to access the WCF service, I used the "Adding service reference" tool from the Visual Studio to generate the client proxies. The proxies generated do not directly support cookies. To send cookies, I created two utility classes in the "CookieBehavior.cs" file.

C#
using System;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
 
namespace WCFClient
{
    public class CookieBehavior : IEndpointBehavior
    {
        private string cookie;
 
        public CookieBehavior(string cookie)
        {
            this.cookie = cookie;
        }
 
        public void AddBindingParameters(ServiceEndpoint serviceEndpoint,
            System.ServiceModel.Channels
            .BindingParameterCollection bindingParameters) { }
 
        public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint,
            System.ServiceModel.Dispatcher.ClientRuntime behavior)
        {
            behavior.MessageInspectors.Add(new CookieMessageInspector(cookie));
        }
 
        public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint,
            System.ServiceModel.Dispatcher
            .EndpointDispatcher endpointDispatcher) { }
 
        public void Validate(ServiceEndpoint serviceEndpoint) { }
    }
 
    public class CookieMessageInspector : IClientMessageInspector
    {
        private string cookie;
 
        public CookieMessageInspector(string cookie)
        {
            this.cookie = cookie;
        }
 
        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,
            object correlationState) { }
 
        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
            System.ServiceModel.IClientChannel channel)
        {
            HttpRequestMessageProperty httpRequestMessage;
            object httpRequestMessageObject;
            if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name
                , out httpRequestMessageObject))
            {
                httpRequestMessage = httpRequestMessageObject 
					as HttpRequestMessageProperty;
                if (string.IsNullOrEmpty(httpRequestMessage.Headers["Cookie"]))
                {
                    httpRequestMessage.Headers["Cookie"] = cookie;
                }
            }
            else
            {
                httpRequestMessage = new HttpRequestMessageProperty();
                httpRequestMessage.Headers.Add("Cookie", cookie);
                request.Properties.Add(HttpRequestMessageProperty.Name
                    , httpRequestMessage);
            }
 
            return null;
        }
    }
}
  • The "CookieMessageInspector" class implements the "IClientMessageInspector" interface. In the "BeforeSendRequest" method, the cookie in the form of a string is added to the request message to the WCF service.
  • The "CookieBehavior" implements the "IEndpointBehavior" interface. In the "ApplyClientBehavior" method, an instance of the "CookieMessageInspector" class is added to the "MessageInspectors" collection.

With the help of these two utility classes, we can then insert the cookies into the client proxies. The "MainWindow.xaml" file is the single window UI of the test program.

XML
<Window x:Class="WCFClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        FontFamily="Calibri"
        Height="250" Width="525">
    
    <Grid Margin="15">
        <Button Content="Test Sending Cookie" Click="TestSendingCookie_Click" />
    </Grid>
</Window>

The code-behind file of the "MainWindow.xaml" is implemented as the following:

C#
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using WCFClient.ServiceWithCookies;
 
namespace WCFClient
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private void TestSendingCookie_Click(object sender, RoutedEventArgs e)
        {
            // This is the cookie string
            // referring to: http://en.wikipedia.org/wiki/HTTP_cookie#Setting_a_cookie
            string cookieString = "President=Barack Hussein Obama II";
            CookieBehavior b = new CookieBehavior(cookieString);
            ServiceWithCookiesClient client = new ServiceWithCookiesClient();
            client.Endpoint.Behaviors.Add(b);
 
            CookieInformation info = client.EchoCookieInformation();
            MessageBox.Show("Key=" + info.Key + ", Value=" + info.Value);
        }
    }
}

In the "Click" event of the button, I first formulated the cookie string. The cookie string to send to the server is simply a key/value pair. If you want to know more about the formatting of the cookie strings, you can take a look at this link. I then initiated a "CookieBehavior" object with the cookie string and associated it with the WCF client. When the WCF call finishes, the information from the call is displayed in a "MessageBox".

Now we can take a look at how the WCF client runs.

Run the Example

Set the "WCFClient" project as the start up project, we can debug run the example. When the application launches, we can see the single button window as the following:

RunApplication01.JPG

Click on the button and wait until the WCF call finishes, we can see the following message box.

RunApplication02.JPG

As we can see, both the key and the value of the cookie sent to the service are successfully received by the server and "echoed" back to the client.

Points of Interest

  • This article presented an example on how to send cookies when making WCF calls.
  • If you are calling a "REST" service using the "WebClient", you should have some simpler ways to send cookies to the service. The method introduced here is targeting to the case when we are calling a regular WCF service and we are using the "Adding service reference" tool from the Visual Studio to generate the client proxies.
  • In most cases, we should not have the necessity to send cookies when we make WCF calls. But if the service is behind a "Forms Authentication" mechanism, we will need to send the authentication cookie to gain access to the service.
  • I hope you like my postings and I hope this article can help you one way or the other.

History

  • 2011-05-04: First revision

License

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