WCF会话
在asp.net中,会话大家应该已经很熟悉,WCF也提供了会话,但是不同的是WCF的会话并没有提供会话的数据缓存共享区域。
其中ServiceContract有个属性,SessionMode,有三个模式:
1、Allowed:指定当传入绑定支持会话时,协定也支持会话
2、Required:指定协定需要会话绑定。如果绑定并未配置为支持会话,则将引发异常。
3、NotAllowed: 指定协定永不支持启动会话的绑定。
其中第二点,之前看了一些博文,解释为:所有调用(即,支持调用的基础消息交换)都必须是同一个对话的一部分。
这种解释其实很难让人明白,MSND的解释已经很明白,会话绑定的协议httpBinding不支持会话,如果配置为比如httpBinding的绑定,那么就会抛异常。
其中,如果配置为TCP,那么,该值必须是Required。
首先来看一下契约的定义,这里做了一个双工的会话,模式为Required。
[ServiceContract(CallbackContract =typeof(ICalculateCallback),SessionMode =SessionMode.Required)] public interface ICalculate { [OperationContract(IsOneWay =true,IsTerminating =true)] void Add(int a, int b); [OperationContract(IsOneWay =true,IsInitiating =true)] void SubStract(int a, int b); }
这个例子,我们看到除了在服务契约上做了一些会话的定义,在操作上,我们可以看到,Add接口定义了IsTerminating=true,SubStract定义了IsInistating,我们分别来看一下这两个属性的作用。
IsTerminating:获取或设置一个值,该值指示服务操作在发送答复消息(如果存在)后,是否会导致服务器关闭会话。
那么返回值为:如果该操作会导致服务器关闭会话,则为 true;否则为 false。默认值为 false。
这也是这个例子为什么用双工通信来做演示,双工通信做回调处理,如果定义为true,再执行回调处理,那么服务器会话已经关闭,不允许再发送回调消息,如果依然做了回调处理,或者在调用在该服务上定义的操作,就会抛出异常。
IsInitiating:获取或设置一个值,该值指示方法是否实现可在服务器上启动会话(如果存在会话)的操作。
如果允许操作启动服务器上的会话,则为 true;否则为 false。默认值为 true。
回调声明:
public interface ICalculateCallback { [OperationContract(IsOneWay =true)] void Show(int result); }
下面是客户端定义的服务回调:
public class CalculateCallback : ICalculateCallback { public void Show(int result) { Console.WriteLine("结果呈现:" + result); } }
服务的实现:
public class ServiceCalculator : ICalculate { int result = 0; public void Add(int a, int b) { try { result += a / b; //OperationContext.Current.GetCallbackChannel<ICalculateCallback>().Show(result); } catch (Exception ex) { throw new FaultException<FaultMessage>(new FaultMessage() { Messgae = ex.Message, Code = 20101 }); } } public void SubStract(int a, int b) { result+= a - b; OperationContext.Current.GetCallbackChannel<ICalculateCallback>().Show(result); } }
客户端的调用:
static void Main(string[] args) { CalculateClient client = new CalculateClient(new InstanceContext(new CalculateCallback())); client.SubStract(30, 4); client.Add(100,5); Console.ReadLine(); }
得到结果是26,这里Add没有执行回调,我们把IsTerminating设置为fasle,Add再执行调用,我们来看一下结果:
我们可以看到result的值执行SubStract得到26,再执行Add计算100/5得到20加上之前得到计算结果26,那么得到了46,在会话调用,期间会保存了上一次调用的结果。