[WCF 学习笔记] 6. 会话状态
2009-01-17 15:02
246 查看
WCF 会话状态和两个端点(EndPoint)之间的一系列消息交换相关联,它实际上是 "实例上下文(Instance Context)”,控制着服务对象实例的创建方式和生存期。和 ASP.NET Session 有很大不同。
WCF Session 特点:
由调用程序(Calling Application)发起初始化和终止操作。
由具体的 Binding 类型实现,因此它们之间的细节可能有所不同。
不提供 ASP.NET Session 那样的数据容器。
启动 Session 的方法包括:
调用 Channel 的 Open 方法。我们可以使用 ChannelFactory 来创建 Channel。
调用客户端代理对象的 Open 方法(ClientBase.Open)。
调用任何允许初始化会话服务方法(缺省情况下所有的服务方法都自动初始化Session,也就是 IsInitiating=true)。
结束 Session 的方法包括:
调用 Channel 的 Close 方法。
调用客户端代理对象的 Close 方法(ClientBase.Close)。
调用任何包含 "IsTerminating=true" 声明的服务方法(缺省情况下所有的服务方法 IsTerminating=false,需要我们显示声明)。
要使用 WCF Session,我们一般按如下步骤进行。
1. 开启服务契约的 Session。
可
以选择的模式包括:Required、Allowed、NotAllowed。Required 表示必须使用 Session,如果 Binding
不支持,则会抛出异常;Allowed 表示如果 Binding 支持 Session 则开启会话;NotAllowed 表示停用
Session。多数 Binding 缺省就会开始 Session,而 BaseHttpBinding 不支持 Session。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract]
int Add(int a, int b);
}
2. 使用 ServiceBehaviorAttribute 和 InstanceContextMode 在服务契约的实现类型上指定服务对象的 "实例上下文模式"。
InstanceContextMode
可选择的方式包括:PerSession、PerCall、Single。PerSession 表示为每个连接(每个客户端代理对象)
创建一个会话(服务对象);PerCall 则为每次调用(Operate)创建一个会话(服务对象);Single
则表示所有的客户端共享一个会话(服务对象)。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract]
int Add(int a, int b);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculateService : ICalculate
{
public CalculateService()
{
Console.WriteLine("Constructor {0}...", this.GetHashCode());
}
public int Add(int a, int b)
{
Console.WriteLine(OperationContext.Current.SessionId);
return a + b;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new WSHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new WSHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
Console.WriteLine(o.Add(1, 2));
Console.WriteLine(o.Add(1, 2));
Console.WriteLine(o.Add(1, 2));
}
}
输出:
Constructor 30136159...
urn:uuid:9fc72020-3ba3-442b-be1c-f2faf06a46d3
3
urn:uuid:9fc72020-3ba3-442b-be1c-f2faf06a46d3
3
urn:uuid:9fc72020-3ba3-442b-be1c-f2faf06a46d3
3
3. 如果有必要,可以使用 OperationContractAttribute 的 IsInitiating 和 IsTerminating 属性来控制每次调用对 Session 的操控。
IsInitiating 表示该方法是否可以初始化 Session,IsTerminating 表示该方法是否可以终止 Session。默认设置 IsInitiating=true,IsTerminating=false。
我们将上面例子改一下。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract(IsTerminating=true)]
int Add(int a, int b);
}
在客户端第二次调用 Add 方法时会抛出异常。
未处理 System.InvalidOperationException
Message="This channel cannot send any more messages because IsTerminating operation 'Add' has already been called."
Source="mscorlib"
StackTrace:
Server stack trace:
在
System.ServiceModel.Channels.ServiceChannel.PrepareCall(ProxyOperationRuntime
operation, Boolean oneway, ProxyRpc& rpc)
......
我们继续修改上面例子。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract(IsInitiating = false)]
int Add(int a, int b);
}
第一次调用 Add 方法,触发异常。
未处理 System.InvalidOperationException
Message="ContractDescription
'ICalculate' has zero IsInitiating=true operations; a contract must
have at least one IsInitiating=true operation."
Source="System.ServiceModel"
StackTrace:
在 System.ServiceModel.Description.ContractDescription.EnsureInvariants()
......
我们可以增加一个额外的方法来初始化会话,如下。OK,这次没问题了。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract(IsInitiating=true)]
void Initiate();
[OperationContract(IsInitiating=false)]
int Add(int a, int b);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculateService : ICalculate
{
public CalculateService()
{
Console.WriteLine("Constructor {0}...", this.GetHashCode());
}
public void Initiate()
{
}
public int Add(int a, int b)
{
Console.WriteLine(OperationContext.Current.SessionId);
return a + b;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new WSHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new WSHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
o.Initiate();
Console.WriteLine(o.Add(1, 2));
}
}
WCF Session 特点:
由调用程序(Calling Application)发起初始化和终止操作。
由具体的 Binding 类型实现,因此它们之间的细节可能有所不同。
不提供 ASP.NET Session 那样的数据容器。
启动 Session 的方法包括:
调用 Channel 的 Open 方法。我们可以使用 ChannelFactory 来创建 Channel。
调用客户端代理对象的 Open 方法(ClientBase.Open)。
调用任何允许初始化会话服务方法(缺省情况下所有的服务方法都自动初始化Session,也就是 IsInitiating=true)。
结束 Session 的方法包括:
调用 Channel 的 Close 方法。
调用客户端代理对象的 Close 方法(ClientBase.Close)。
调用任何包含 "IsTerminating=true" 声明的服务方法(缺省情况下所有的服务方法 IsTerminating=false,需要我们显示声明)。
要使用 WCF Session,我们一般按如下步骤进行。
1. 开启服务契约的 Session。
可
以选择的模式包括:Required、Allowed、NotAllowed。Required 表示必须使用 Session,如果 Binding
不支持,则会抛出异常;Allowed 表示如果 Binding 支持 Session 则开启会话;NotAllowed 表示停用
Session。多数 Binding 缺省就会开始 Session,而 BaseHttpBinding 不支持 Session。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract]
int Add(int a, int b);
}
2. 使用 ServiceBehaviorAttribute 和 InstanceContextMode 在服务契约的实现类型上指定服务对象的 "实例上下文模式"。
InstanceContextMode
可选择的方式包括:PerSession、PerCall、Single。PerSession 表示为每个连接(每个客户端代理对象)
创建一个会话(服务对象);PerCall 则为每次调用(Operate)创建一个会话(服务对象);Single
则表示所有的客户端共享一个会话(服务对象)。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract]
int Add(int a, int b);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculateService : ICalculate
{
public CalculateService()
{
Console.WriteLine("Constructor {0}...", this.GetHashCode());
}
public int Add(int a, int b)
{
Console.WriteLine(OperationContext.Current.SessionId);
return a + b;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new WSHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new WSHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
Console.WriteLine(o.Add(1, 2));
Console.WriteLine(o.Add(1, 2));
Console.WriteLine(o.Add(1, 2));
}
}
输出:
Constructor 30136159...
urn:uuid:9fc72020-3ba3-442b-be1c-f2faf06a46d3
3
urn:uuid:9fc72020-3ba3-442b-be1c-f2faf06a46d3
3
urn:uuid:9fc72020-3ba3-442b-be1c-f2faf06a46d3
3
3. 如果有必要,可以使用 OperationContractAttribute 的 IsInitiating 和 IsTerminating 属性来控制每次调用对 Session 的操控。
IsInitiating 表示该方法是否可以初始化 Session,IsTerminating 表示该方法是否可以终止 Session。默认设置 IsInitiating=true,IsTerminating=false。
我们将上面例子改一下。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract(IsTerminating=true)]
int Add(int a, int b);
}
在客户端第二次调用 Add 方法时会抛出异常。
未处理 System.InvalidOperationException
Message="This channel cannot send any more messages because IsTerminating operation 'Add' has already been called."
Source="mscorlib"
StackTrace:
Server stack trace:
在
System.ServiceModel.Channels.ServiceChannel.PrepareCall(ProxyOperationRuntime
operation, Boolean oneway, ProxyRpc& rpc)
......
我们继续修改上面例子。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract(IsInitiating = false)]
int Add(int a, int b);
}
第一次调用 Add 方法,触发异常。
未处理 System.InvalidOperationException
Message="ContractDescription
'ICalculate' has zero IsInitiating=true operations; a contract must
have at least one IsInitiating=true operation."
Source="System.ServiceModel"
StackTrace:
在 System.ServiceModel.Description.ContractDescription.EnsureInvariants()
......
我们可以增加一个额外的方法来初始化会话,如下。OK,这次没问题了。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
[OperationContract(IsInitiating=true)]
void Initiate();
[OperationContract(IsInitiating=false)]
int Add(int a, int b);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculateService : ICalculate
{
public CalculateService()
{
Console.WriteLine("Constructor {0}...", this.GetHashCode());
}
public void Initiate()
{
}
public int Add(int a, int b)
{
Console.WriteLine(OperationContext.Current.SessionId);
return a + b;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new WSHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new WSHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
o.Initiate();
Console.WriteLine(o.Add(1, 2));
}
}
相关文章推荐
- WCF学习笔记之实例与会话(Instance And Session)
- ASP.NET 3.5核心编程学习笔记(34):会话状态的使用
- WCF学习笔记之可靠会话
- ASP.NET 3.5核心编程学习笔记(35):会话状态的自定义管理
- [原创]java WEB学习笔记31:会话与状态管理 session机制 概述(定义,session机制,session的声明周期,保存session的方式,Session的创建与删除)
- [原创]java WEB学习笔记28: 会话与状态管理Cookie 机制
- 【EJB学习笔记】——有状态的会话Bean和无状态的会话Bean
- WCF学习笔记之消息交换模式
- 【学习笔记javascript设计模式与开发实践(状态模式)----16】
- WCF 学习笔记之双工实现
- 华为防火墙学习总结:二、状态检测和会话机制
- JAVA学习笔记50——线程状态+停止进程+阻塞进程
- Java并发学习笔记(6)线程的四种状态,优先级
- EntityFramework:状态变化与方法的关系(朋友的学习笔记)
- 统计学 学习笔记 (三)—— 掌握数据的整体状态 数据的变异性
- JavaWeb学习笔记五 会话技术Cookie&Session
- Kaldi决策树状态绑定学习笔记(四)
- wcf 学习笔记2
- 开源HSM学习笔记---状态相关的行为动作
- IOS学习笔记43--IOS App在ItunesConnect里面的几种状态