发出 WCF 服务调用时发送 Cookie
本文介绍了一个在进行 WCF 服务调用时如何发送 Cookie 的示例。
引言
本文介绍了一个在进行 WCF 服务调用时如何发送 Cookie 的示例。
背景
有时,你可能希望在进行 WCF 调用时,以“Cookie”的形式向服务器发送一些信息。例如,如果 WCF 服务受到“Forms Authentication”机制的保护,你就需要在进行 WCF 调用时发送身份验证 Cookie,以获得访问服务的必要权限。
- 如果你使用“WebClient”类调用“REST”服务,这应该不是一个难题。你可以直接操作“HttpWebRequest”类的“CookieContainer”属性。
- 如果你调用的是常规 WCF 服务,并且你的客户端代理是由 Visual Studio 中的“添加服务引用”工具生成的,那么发送 Cookie 的方法就不那么明显了。
本文旨在提供一个示例,说明如何使用 Visual Studio 生成的客户端代理在进行 WCF 调用时发送 Cookie。

随附的 Visual Studio 解决方案是在 Visual Studio 2010 中开发的。它有两个项目:
- “
WCFHost
”是一个简单的 ASP.NET MVC 项目,用于托管示例 WCF 服务。 - “
WCFClient
”是一个简单的 WPF 项目。我将在该项目中向你展示如何在调用 WCF 服务时发送 Cookie。
让我们首先来看一下 WCF 服务。
WCF服务
示例 WCF 服务实现在“WCFHost
”项目中的“ServiceWithCookies.svc.cs”文件里。
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
};
}
}
}
- “DataContract”类“
CookieInformation
”有两个字段,名为“Key
”和“Value
”。 - “OperationContract”方法“
EchoCookieInformation
”实现了读取客户端的 Cookie,并将信息放入“CookieInformation
”类的一个实例中。
通过 Cookie 将应用程序数据发送到 WCF 服务并不是“推荐”的业务数据通信方式。在此示例中,从客户端读取 Cookie 的目的完全是为了展示 WCF 客户端确实可以向服务器发送 Cookie。为了让 WCF 服务方法“EchoCookieInformation
”能够访问“HttpContext”,我们需要在“<system.serviceModel>
”标签内的“web.config”文件中添加以下内容:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
现在我们可以看看客户端是如何发送 Cookie 的。
WCF 服务客户端
为了访问 WCF 服务,我使用了 Visual Studio 的“添加服务引用”工具生成了客户端代理。生成的代理不直接支持 Cookie。为了发送 Cookie,我在“CookieBehavior.cs”文件中创建了两个实用类。
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;
}
}
}
- “
CookieMessageInspector
”类实现了“IClientMessageInspector”接口。在“BeforeSendRequest
”方法中,以string
形式的 Cookie 被添加到发送到 WCF 服务的请求消息中。 - “
CookieBehavior
”实现了“IEndpointBehavior”接口。在“ApplyClientBehavior
”方法中,将“CookieMessageInspector
”类的一个实例添加到“MessageInspectors”集合中。
借助这两个实用类,我们就可以将 Cookie 插入客户端代理。 "MainWindow.xaml" 文件是测试程序的单个窗口 UI。
<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>
“MainWindow.xaml”的代码隐藏文件实现如下:
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);
}
}
}
在按钮的“Click
”事件中,我首先构建了 Cookie 字符串。要发送到服务器的 Cookie 字符串就是一个简单的键值对。如果你想了解更多关于 Cookie 字符串格式的信息,可以查看此链接。然后,我初始化了一个带有 Cookie 字符串的“CookieBehavior
”对象,并将其与 WCF 客户端关联起来。当 WCF 调用完成后,来自调用的信息会显示在“MessageBox
”中。
现在我们可以看看 WCF 客户端是如何运行的。
运行示例
将“WCFClient
”项目设置为启动项目,我们可以调试运行此示例。应用程序启动时,我们将看到如下的单个按钮窗口:
单击按钮并等待 WCF 调用完成,我们可以看到如下的消息框:
正如我们所见,发送到服务的 Cookie 的键和值都已成功被服务器接收并“回显”到客户端。
关注点
- 本文介绍了一个在进行 WCF 调用时如何发送 Cookie 的示例。
- 如果你使用“
WebClient
”调用“REST”服务,你应该有更简单的方法来发送 Cookie。这里介绍的方法是针对调用常规 WCF 服务并使用 Visual Studio 的“添加服务引用”工具生成客户端代理的情况。 - 在大多数情况下,我们不应该有在进行 WCF 调用时发送 Cookie 的必要。但如果服务受到“Forms Authentication”机制的保护,我们就需要发送身份验证 Cookie 来获得对该服务的访问权限。
- 我希望您喜欢我的文章,希望本文能以某种方式帮助您。
历史
- 2011-05-04:首次修订