HttpCookieSession 示例演示如何生成自定义协议通道,以使用 HTTP Cookie 进行会话管理。 此通道支持 Windows Communication Foundation (WCF) 服务和 ASMX 客户端之间或 WCF 客户端与 ASMX 服务之间的通信。
当客户端在基于会话的 ASMX Web 服务中调用 Web 方法时,ASP.NET 引擎执行以下作:
生成唯一 ID(会话 ID)。
生成会话对象并将其与唯一 ID 相关联。
将唯一 ID 添加到 Set-Cookie HTTP 响应标头,并将其发送到客户端。
根据客户端发送到它的会话 ID 在后续调用中标识客户端。
客户端在其后续对服务器的请求中包含此会话 ID。 服务器使用客户端的会话 ID 为当前 HTTP 上下文加载相应的会话对象。
HttpCookieSession 通道消息交换模式
此示例可为类似ASMX的场景启用会话功能。 在我们的通道堆栈底部,我们具有支持 IRequestChannel 和 IReplyChannel的 HTTP 传输。 通道的任务是向通道堆栈中的更高层提供会话。 此示例实现支持会话的两个通道(IRequestSessionChannel 和 IReplySessionChannel)。
服务通道
此示例在HttpCookieReplySessionChannelListener
类中提供服务通道。 此类实现 IChannelListener 接口,并将通道堆栈中位于较低层的 IReplyChannel 通道转换为 IReplySessionChannel。 此过程可以分为以下部分:
当通道侦听器打开时,它接受来自其内部侦听器的内部通道。 由于内部侦听器是数据报侦听器,并且接受通道的生存期与侦听器的生存期分离,因此我们可以关闭内部侦听器,并且只保留内部通道
this.innerChannelListener.Open(timeoutHelper.RemainingTime()); this.innerChannel = this.innerChannelListener.AcceptChannel(timeoutHelper.RemainingTime()); this.innerChannel.Open(timeoutHelper.RemainingTime()); this.innerChannelListener.Close(timeoutHelper.RemainingTime());
打开的进程完成后,我们设置了一个消息循环,用于从内部通道接收消息。
IAsyncResult result = BeginInnerReceiveRequest(); if (result != null && result.CompletedSynchronously) { // do not block the user thread this.completeReceiveCallback ??= new WaitCallback(CompleteReceiveCallback); ThreadPool.QueueUserWorkItem(this.completeReceiveCallback, result); }
当消息到达后,服务通道检查会话标识符并多路分解到相应的会话通道。 通道侦听器维护一个字典,该字典将会话标识符映射到会话通道实例。
Dictionary<string, IReplySessionChannel> channelMapping;
类 HttpCookieReplySessionChannel
实现 IReplySessionChannel。 通道堆栈的较高级别调用 ReceiveRequest 该方法来读取此会话的请求。 每个会话通道都有一个由服务通道填充的专用消息队列。
InputQueue<RequestContext> requestQueue;
如果有人调用 ReceiveRequest 该方法且消息队列中没有消息,通道会在关闭自身之前等待指定的时间量。 这会清理为非 WCF 客户端创建的会话通道。
我们使用 channelMapping
跟踪 ReplySessionChannels
,并且在所有已接受的通道全部关闭之前不会关闭基础 innerChannel
。 这种方法 HttpCookieReplySessionChannel
可以存在于 HttpCookieReplySessionChannelListener
的生命周期之外。 我们也无需担心侦听器会在我们下面收集垃圾,因为已接受的通道通过 OnClosed
回调保留对其侦听器的引用。
客户端通道
相应的客户端通道位于类中 HttpCookieSessionChannelFactory
。 在通道创建过程中,通道工厂使用HttpCookieRequestSessionChannel
包装内部请求通道。 该 HttpCookieRequestSessionChannel
类将呼叫转发至底层请求通道。 当客户端关闭代理时, HttpCookieRequestSessionChannel
向服务发送一条消息,指示通道正在关闭。 因此,服务通道堆栈可以正常关闭正在使用的会话通道。
绑定和绑定元素
创建服务和客户端通道后,下一步是将它们集成到 WCF 运行时。 通道通过绑定和绑定元素公开给 WCF。 绑定由一个或多个绑定元素组成。 WCF 提供多个系统定义的绑定;例如,BasicHttpBinding 或 WSHttpBinding。 该 HttpCookieSessionBindingElement
类包含绑定元素的实现。 它重写通道侦听器和通道工厂创建方法,以进行必要的通道侦听器或通道工厂实例化。
该示例在服务描述中使用了策略断言。 这允许示例将其通道要求发布到其他可以使用该服务的客户端。 例如,此绑定元素发布策略断言,让潜在客户端知道它支持会话。 由于该示例启用 ExchangeTerminateMessage
绑定元素配置中的属性,从而添加必要的断言,以显示服务支持额外的消息交换操作来终止会话对话。 然后,客户可以使用此操作。 以下 WSDL 代码显示从 HttpCookieSessionBindingElement
创建的策略断言。
<wsp:Policy wsu:Id="HttpCookieSessionBinding_IWcfCookieSessionService_policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<wspe:Utf816FFFECharacterEncoding xmlns:wspe="http://schemas.xmlsoap.org/ws/2004/09/policy/encoding"/>
<mhsc:httpSessionCookie xmlns:mhsc="http://samples.microsoft.com/wcf/mhsc/policy"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
该 HttpCookieSessionBinding
类是一个系统提供的绑定,它使用前面所述的绑定元素。
将通道添加到配置系统
此示例提供了两个类,它们通过配置公开示例通道。 第一个类是适用于 BindingElementExtensionElement 的 HttpCookieSessionBindingElement
。 批量实现委派给从 HttpCookieSessionBindingConfigurationElement
派生的 StandardBindingElement。
HttpCookieSessionBindingConfigurationElement
的属性与 HttpCookieSessionBindingElement
上的属性相对应。
绑定元素扩展节
HttpCookieSessionBindingElementSection
节是一个 BindingElementExtensionElement,它向配置系统公开 HttpCookieSessionBindingElement
。 通过对配置节名称进行一些重写,可以定义绑定元素的类型以及如何创建绑定元素。 然后,我们可以在配置文件中注册扩展部分,如下所示:
<configuration>
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="httpCookieSession"
type=
"Microsoft.ServiceModel.Samples.HttpCookieSessionBindingElementElement,
HttpCookieSessionExtension, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null"/>
</bindingElementExtensions >
</extensions>
<bindings>
<customBinding>
<binding name="allowCookiesBinding">
<textMessageEncoding messageVersion="Soap11WSAddressing10" />
<httpCookieSession sessionTimeout="10" exchangeTerminateMessage="true" />
<httpTransport allowCookies="true" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
测试代码
客户端和服务目录中提供了使用此示例传输的测试代码。 它包含两个测试 - 一个测试在客户端使用 allowCookies
设置为 true
的绑定。 第二个测试在该绑定上实现显式关闭(使用终止消息交换)。
运行示例时,应会看到以下输出:
Simple binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3
Smart binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3
Press <ENTER> to terminate client.
设置、生成和运行示例
使用以下命令安装 ASP.NET 4.0。
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。
要生成解决方案,请按照生成 Windows Communication Foundation 示例中的说明进行操作。
若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。