原文:WCF常见问题(1) -- WebService/WCF Session Cookie

在.net 3.0推出WCF之前使用的WebService,有的应用有使用Session保持一些信息,在不同的WebMethod中共享存储信息。比如:保持登陆用户的信息等。其原理是应用ASP.NET兼容模式,利用HttpContext来保持请求的上下文。

为了显示WebService/WCF不同应用下的Session/Cookie应用,这里分别创建两个Service应用:一个是WebService Application(.net 4.0下没有此模板,只有在.net 3.5以下版本中有),一个是WCFService Application(IIS宿主的WCF应用)
整体solution图:


1. WebService Application(*.asmx) + .net 2.0 Client Proxy
可以看到 Login 方法里将登录的 userName 保存在 Session 里。在 GetUserName 方法返回 Session 中的数据。
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod(EnableSession=true)]
public void Login(string user)
{
var session = HttpContext.Current.Session;
session["user"] = user;
HttpContext.Current.Response.Cookies.Add(new HttpCookie("user", user));
}
[WebMethod(EnableSession = true)]
public string GetUserName()
{
return HttpContext.Current.Session["user"] as string;
}
}
先来看看 .net 2.0 中的客户端如何保持 Session 的。
ASP.NET 中的客户端也就是浏览器端会通过Cookie来保持 Session。所以对于 WebService 的客户端需要自己去维护一个 CookieContainer。(服务端需要没一个WebMethod都需要设定EnableSession=true)
CookieContainer cookieContainer = new CookieContainer();
而每次调用都必须添加这个cookieContainer的实例。
PS: .net 3.5里仍然可以使用.net 2.0生成客户端:Add Service Reference -> Advance -> Add Web Reference

添加完WebService Reference后客户端调用:
using (var svc = new MyWebSvc.Service1())
{
svc.CookieContainer = cookieContainer;
svc.Login(textBox1.Text);
}
再一次调用:
using (var svc = new MyWebSvc.Service1())
{
svc.CookieContainer = cookieContainer;
label1.Text = svc.GetUserName();
}
OK,现在的客户端实现了cookie的保持,每次调用Service方法时,Service会携带之前的cookie信息,则在服务端则能识别调用的Session而返回对应的数据。

2. WebService Application(*.asmx) + .net 3.5 Client Proxy
服务端代码没有变化,客户端引用则修改为 Add Service Reference .net 3.5 生成客户端代理。
这次生成的客户端代理中已经找不到 svc 中的 CookieContainer 属性,难道不能保持客户端 cookie 了吗?
检查客户端生成 app.config (.net 3.5里的WebService原来使用的是basicHttpBinding)
<system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="Service1Soap" allowCookies="false" ......
原来 allowCookies 默认设为 false 了,我们把它改为:true 就OK了。
using (var svc = new MyWCFWebSvc.Service1SoapClient())
{
svc.Login(textBox1.Text);
}
再次调用:
using (var svc = new MyWCFWebSvc.Service1SoapClient())
{
label1.Text = svc.GetUserName();
}

3. WCF Service Application(*.svc) + .net 3.5 Client Proxy
WCF的ServiceContract
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetUserName();
[OperationContract]
void Login(string user);
}
Service的实现,类似上面的WebMethod
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public void Login(string user)
{
var session = HttpContext.Current.Session;
session["user"] = user;
HttpContext.Current.Response.Cookies.Add(new HttpCookie("user", user));
}
public string GetUserName()
{
return HttpContext.Current.Session["user"] as string;
}

WCF Service Application的工程模板中,默认是没有启用ASP.NET兼容模式的,这个时候直接调用 HttpContext 将返回 null。
所以需要设置 AspNetCompatibilityRequirements 特性:
1)[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
2)服务端配置文件也需要修改,在 <system.serviceModel> 节点中,添加如下配置:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
客户端生成的配置文件 app.config 也同样需要设置

<system.serviceModel>
        <bindings>
              <wsHttpBinding>
                  <binding name="WSHttpBinding_IService1" allowCookies="true" ......

运行效果:

上面的代码中,cookie只在应用程序的生存周期内有效,也就是说当程序关闭,cookie就失效了。服务端也就不能取得对应的session信息了。如果一定要实现类似浏览器浏览网页,今天登陆明天再开还能有效呢?那就得自己来维持这个CookieContainer了,也就是说持久化这个对象。不过遗憾的是在.net3.0以上版本直接添加Service Reference的本地代理中,并没有CookieContainer属性。只能选择使用.net2.0生成客户端代理。持久化CookieContainer的代码如下:
 CookieContainer cookieContainer = new CookieContainer();
private void Form1_Load(object sender, EventArgs e)
{
var cookieFile = "MyCookie.dat";
if (File.Exists(cookieFile))
{
using (var fs = File.OpenRead(cookieFile))
{
var bf = new BinaryFormatter();
cookieContainer = bf.Deserialize(fs) as CookieContainer;
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
var cookieFile = "MyCookie.dat";
using (var fs = File.OpenWrite(cookieFile))
{
var bf = new BinaryFormatter();
bf.Serialize(fs, cookieContainer);
}
}

WCF常见问题(1) -- WebService/WCF Session Cookie的更多相关文章

  1. 关于通信的关键词UDP/(TCP/IP)/IPC/RPC/.NET Remoting/WebService/WCF/Http 系列

    OSI七层和TCP/IP四层的关系 1.1 OSI引入了服务.接口.协议.分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型. 1.2 OSI先有模型,后有协议,先有标准,后进行实践: ...

  2. .Net remoting, Webservice,WCF,Socket区别

    传统上,我们把计算机后台程序(Daemon)提供的功能,称为"服务"(service).比如,让一个杀毒软件在后台运行,它会自动监控系统,那么这种自动监控就是一个"服务& ...

  3. 不用webservice wcf提供服务,用Rest更轻量

    从2005年开始就开始有基于服务的开发方式,到08年时候 微软和sun等公司都已经提供了很多基于服务的开发框架 . 微软 .net 平台的基于服务的框架主要有:.NET Remoting.webser ...

  4. Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor

    Webservice WCF WebApi   注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...

  5. session cookie原理及应用

    一.术语session在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相同的. session,中 ...

  6. C#调用WebService时插入cookie

    SOAPUI插入Cookie的方法 SOAP插入cookie的方法如下,点击Head,点击加号,然后直接设置就可以了. C#中调用webService时插入Cookie 由于调用的时候必须要带上coo ...

  7. WCF入门教程1——WCF简要介绍

    什么是WCF Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台. 整合了原有的windo ...

  8. WCF系列教程之WCF服务宿主与WCF服务部署

    本文参考自http://www.cnblogs.com/wangweimutou/p/4377062.html,纯属读书笔记,加深记忆. 一.简介 任何一个程序的运行都需要依赖一个确定的进程中,WCF ...

  9. WCF学习之旅—WCF寄宿前的准备(八)

    一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类协定的定 ...

随机推荐

  1. BZOJ 1901 Dynamic Rankings 树董事长

    标题效果:间隔可以改变k少 我的两个天树牌主席... 隔断Count On A Tree 之后我一直认为,随着树的主席的变化是分域林木覆盖率可持久段树. .. 事实上,我是误导... 尼可持久化线段树 ...

  2. 拆除vs发展c++程序开发过程中产生的.ipch和.sdf文件的方法

    正在使用Visual Studio 2010发展C++当程序,你会发现,有创建一些奇怪的文件.一个叫ipch的目录,和一个与project同名的.sdf文件.并且ipch以下的文件和.sdf文件都非常 ...

  3. 概率统计(DP)

    问题叙述性说明 生成n个月∈[a,b]随机整数.并且将它们输出到x概率. 输入格式 输入线跟四个整数n.a,b,x,用空格分隔. 输出格式 输出一行包括一个小数位和为x的概率.小数点后保留四位小数 例 ...

  4. HDU2149-Public Sale

    Public Sale Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  5. jQuery EasyUI实现全部关闭tabs

    有时,当我们打开很多tabs当标签,要关闭一个接一个,它只能被关停 显然太麻烦,能够在选项卡的最右边加入一个button 实现关闭所有. 代码例如以下: <!DOCTYPE HTML PUBLI ...

  6. OC本学习笔记Foundatio框架集

        一.OC数组         OC数组是一个类,它也分不可变数组NSArray和可变数组NSMutableArray. 1➣不可变数组的创建 // 创建一个不可变数组.元素为一个OC字符串对象 ...

  7. RandomAccessFile实时读取大文件(转)

    最近有一个银行数据漂白系统,要求操作人员在页面调用远端Linux服务器的shell,并将shell输出的信息保存到一个日志文件,前台页面要实时显示日志文件的内容.这个问题难点在于如何判断哪些数据是新增 ...

  8. “采用VS2010至MFC4.2发育”最后溶液

    我层2010年这方面的研究进行了简单(http://blog.csdn.net/boweirrking/article/details/5477062),那时候没有深入思考过这当中的原理,最终给出的方 ...

  9. js之第三方工具解析JSON

    1.JSON 仅仅是一种文本字符串.它被存储在 responseText 属性中 为了读取存储在 responseText 属性中的 JSON 数据,须要依据 JavaScript 的 eval 函数 ...

  10. [git] fatal: This operation must be run in a work tree

    正在使用git  init --bare 它的成立裸仓库后,,正在使用git 其他命令将出现fatal:This operation must be run in a work tree 问题,途径: ...