知识大全 Web Service中保持ASP.net的状态

Posted 状态

篇首语:山涧的泉水经过一路曲折,才唱出一支美妙的歌。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Web Service中保持ASP.net的状态相关的知识,希望对你有一定的参考价值。

Web Service中保持ASP.net的状态  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  简介 网络程序开发者们遇到的最普遍的问题就是如何在无状态的基于HTTP协议的交互中保持状态信息 有许多聪明的办法可以解决HTTP协议的无状态问题 例如对每个请求重复发送应用程序数据包 使用HTTP认证机制来将请求映射到特定的用户 使用Cookie来存储一系列请求的状态等 在技术中提供了一个非常有效的方案来保持状态 该方案隐藏了所有高难度的 具有挑战性的工作的细节 用户只需简单地使用System Web SessionState HttpSessionState类 同时 你也可以像在程序的Web页面( aspx)中那样在Web Service的方法中使用这个类 只有一点小小的不同 的Session对象概述的Session状态信息是通过两个机制保持 其一是使用Cookie 当客户端发送一个请求到服务器端时 服务器将发回一个附加HTTP Set Cookie头的响应信息 而Cookie的值就是以键/值对的形式保存在该信息里边 在对同一服务器的所有的同步请求中 客户端在HTTP Cookie头中发送Cookie键/值对 然后服务器可以将并发的请求同初始的请求对应起来 使用一个保存会话的ID的cookie来保持会话状态 该ID标识被用来为特定的用户找到与其对应的HttpSessionState类的实例 类HttpSessionState仅仅提供了一个通用的数据集 你可以在其中保存你需要的任何信息 用来保持状态的另外一种机制是无须使用Cookie 一些浏览器被用户设置为禁止使用Cookie或者干脆就不支持Cookie 提供了一种机制来解决这个问题 它的主要原理是将一个请求重定向到一个包含状态ID的URL 当该请求被接受到时 这个嵌在URL中的ID被截取下来 服务器通过该ID找到合适的HttpSessionState类的实例 这种方式在HTTP协议的使用GET方式的请求中工作的很好 但是的XML Web Service代码中会出现问题 必须指出的是 有些时候把信息直接存储在Cookie中要比存储在Session中更好 避免使用Session可以节省服务器资源 而且你也无须考虑一些烦人的问题 比如定位一个特定的Session对象 Session对象因为请求的长时间的延迟而被移除或者在服务器上没必要地保留直到过期 然而 如果你有一些包含你不希望与你提供的服务的使用者共享的执行信息 或者有一些你不希望通过未加密的信道传输的私有数据 或者你认为将这些数据插入HTTP协议头中是不切实际的 那么你就应该使用中的HttpSessionState 它将使你轻松解决这些问题 HttpSessionState类返回一个索引键 用以将一个特定的用户映射到一个为该用户保存信息的HttpSessionState类的实例 总之 无论是的HttpSessionState类还是HTTP的Cookie都可以在 Web Service中使用  为什么要在XML Web Service中使用基于HTTP的机制来实现状态保持呢?在SOAP请求中有许多方法来保持状态 一个切实可行的方法就是在SOAP头中包含一些像ASP中的会话ID的信息 然而问题在于你不得不 ) 仍然要自己编写服务器端代码 并且 ) 确信你的客户会像对待HTTP Cookie一样对待你的包含会话ID的SOAP头并且将它附加到每个请求中回传给你 当然有很多时候使用SOAP头的方法会很方便 但是也有很多时候还不如使用基于HTTP协议的方法 很容易在中使用Session来保持状态信息 HttpSessionState类为你封装了存储Session状态的细节问题 绝大多数的客户端已经能够明白他们必须返回服务器设置的cookie 而且HttpSessionState类也支持在SOAP通信中常用的底层传输 因此 很明显 使用的Session机制会是满足状态控制要求的明智的选择  使服务器支持Session在中 对Web方法的状态支持默认是关闭的 你必须为每个要使用Session状态的Web方法显式地激活Session支持 激活Session支持的方法是添加一个EnableSession选项到你的函数的WebMethod属性中 并且将其值设置为true 下面的代码演示了如何激活Session并且在方法中访问Session状态信息

[]<WebMethod(EnableSession:=True)> _Public Function IncrementSessionCounterX() As IntegerDim counter As IntegerIf Context Session( Counter ) Is Nothing Thencounter = Elsecounter = Context Session( Counter ) + End IfContext Session( Counter ) = counterReturn counterEnd Function

  如你所料 如果你为一个Web方法激活了Session支持 并不意味着其它的Web方法的Session支持也被激活 事实上 如果Web方法的EnableSession选项没有被显式地设置为true 那么Context Session属性的值将是null 假设通过设置nfig文件禁止session 那么即使你在WebMethod属性中使用了EnableSession选项 Context Session的值也将一直是null nfig文件中的/configuration/system web/sessionState项有一个mode参数 它决定了你的程序使用何种方法来保持Session状态 该参数默认设置为 InProc 这时HttpSessionState对象将简单地保存在进程的内存区 如果被设置为 Off 那么程序的Session支持就被关闭了 从服务器端看来 的session状态的有效范围仅仅是某一个给定的应用程序 这就意味着一个HttpSessionState类的实例只能被一个特定用户向某一个虚拟目录发出的所有Session被激活的请求所使用 也就是说 使用同一个会话ID的向其它的虚拟目录的请求将导致不能找到对应的session对象——因为会话ID不是为该应用程序设定的 并不区分对ASPX和ASMX文件的请求 直到该请求需要使用Session对象 因此 理论上你可以在一个Web方法调用和一个普通的ASPX文件之间共享Session状态信息 然而 我们将看到也有些客户端的问题使这个想法变得不那么容易实现 当设置一个HTTP cookie 你可以指定其过期时间 过期时间指定在多久的时间内 客户端应该将该cookie回传给服务器 如果一个cookie没有被设置过期时间 那么它仅仅在该进程处理请求的时间内被回传 例如 IE将一直回传cookie 除非你关闭了浏览器的特定窗口 的用来保存会话ID的Cookie没有过期时间 因此 如果一台客户机上的多个进程向你的服务器上发送HTTP请求 它们也不会共享同一个HttpSessionState对象 甚至两个进程同时运行也是这样 如果你要处理来自同一个进程的并发的Web Service调用 那么这些请求将在服务器上被排序 从而使得在某一时刻只有一个请求被执行 的Web Service不像普通 ASPX页面 支持允许多请求的并发进程的对HttpSessionState对象的只读访问 所有Session被激活的Web方法调用都具有read/write访问的权限 因此必须对之进行排序

  客户端的问题在你的WebService中成功的使用HttpSessionState的功能事实上依赖于对用户的一些假设 首先 也是最重要的一点 如果你是用默认的HTTP Cookie模式来保存Session状态 你的客户端就必须支持cookie 如果你是用无cookie的机制来支持Session 那么你的客户端必须能够并且愿意重定向到一个新的URL 该URL由原来的URL中插入会话ID而得到 结果将表明 这并不是一个无足轻重的问题 它关系到你能否成功地部署你的程序    所有工作都依赖于浏览器如果你是用Microsoft Visual 来开发 Web Service应用程序 那么默认的调试方法就是打开IE访问你的 asmx文件 通常 系统将提供一个可以调用你的Web方法的友好的界面 这是一个调试你的Web Service代码的很好的途径 如果你已经将Web方法的EnableSession选项设置为true 它被非常漂亮地支持 甚至如果你打开了无cookie的Session支持 客户端浏览器也可以完美地完成这项工作 你的Session对象将如你所愿地工作 然而 大多数的Web Service请求不是来自浏览器 而是来自应用程序中的Web引用 我们如何使框架的 添加Web引用 的特性呢?让我们来看一看    添加Web引用的问题我将使用我们前面看到的代码段来创建一个简单的XML Web Service 记起来了吧?这个Web方法被称作IncrementSessionCounter 它仅仅是简单地把一个整数存储在HttpSessionState对象中 然后每次调用则将它加 并且返回当前值 从客户端浏览器我们可以看到这个数字的值随着调用次数的增加而增加 下一步 我创建了一个简单的WinForm应用程序 并且将上述的Web Service添加到Web引用中 下面就是调用我的Web Service的代码 这里并没有与Session打交道Private Sub Button _Click(ByVal sender As System Object _ByVal e As System EventArgs) Handles Button ClickDim proxy As New localhost Service ()Dim ret As Integerret = proxy IncrementSessionCounter()Label Text = Result: & CStr(ret)End Sub当我第一次调用Web Service时 一切正常 Web方法返回 这就是那个Session变量的应有的初始值 现在我点击Button 来再次调用这个Web方法 我希望看到的返回值是 可惜的是 无论我点击多少次Button 返回值一直都是 你也许会怀疑原因就是我每次都创建了一个新的proxy类的实例去调用Web方法 因此每次我点击按钮 都会丢失上一次调用时的cookie 不幸的是 即使你将proxy类的初始化代码移到窗体的构造函数中 然后对每次Web方法调用使用同一个proxy类的实例 你还是不可能看到返回值有增加的迹象 问题在于cookie Web Service代码并未从调用请求中发现有效的会话ID 因此它每次被调用都创建一个全新的HttpSessionState对象 并且返回它的初始值 因为作为客户端的proxy类是从类System Web Service Protocols SoapHttpClientProtocol继承的 它不包含System Net CookieContainer类的实例 因此 没有地方来存放返回的cookie 为了解决这个问题 我对代码做了如下一些修改 使用了ASP NET的session 但是并不是无Cookie的session Private Cookies As System Net CookieContainerPrivate Sub Button _Click(ByVal sender As System Object _ByVal e As System EventArgs) Handles Button ClickDim proxy As New localhost Service ()Dim ret As Integer 为proxy类设置cookie容器If Cookies Is Nothing ThenCookies = New System Net CookieContainer()End Ifproxy CookieContainer = Cookiesret = proxy IncrementSessionCounter()Label Text = Result: & CStr(ret)End Sub

  现在代码工作正常了!每点击一次Button 我都可以看到返回值增加 注意到我并不是在函数中声明变量Cookies的 它是窗体类的一个私有成员 因为如果希望每次都返回同一个会话ID给服务器的话 就必须在每次请求中使用CookieContainer类的同一个实例 这就解释了为什么SoapHttpClientProtocol类默认不自动地设置的cookie容器 正应为此 你可以在多个SoapHttpClientProtocol类的实例中共享一个cookie容器 而不是为其每个实例自动地创建一个新的cookie容器

无cookie的Session从Web Service的开发者的角度来看 你可以想到相当多的人在试图使用你的Web服务时忘记在客户端代理类中添加Cookie容器 聪明的开发者或许灵光一闪 就会发现无cookie的Session应该可以出色地解决这个问题 如果将nfig文件中sessionState元素的cookieless参数设置为 true 你将会发现 通过浏览器界面调用Web方法时 session变量工作正常 但是如果你在Visual 中通过 添加Web引用 来调用它时 依然存在着一些问题 为了研究无cookie的session 我决定使用上面已经使用过的代码 看看它能否在session状态被设置为cookieless的服务器环境中能否工作正常 我也不想费心去删除cookie容器的相关代码 因为我希望得到能在两种session状态下都正常工作的代码 作为一个天生的乐观主义者 我一个字也不改就直接运行它 令人失望的事发生了——不过也不是完全没有想到 我不得不面对这个异常 An unhandled exception of type System Net WebException occurred in system web services dllAdditional information: The request failed with the error message: <><head><title>Object moved</title></head><body><h >Object moved to <a /HttpSessionState/(l z psnhh cf oahmai p )/service asmx >here</a> </h ></body></>发生了什么呢?原来HTTP请求收到的不是 OK 响应 如果你熟悉HTTP协议 你或许可以从响应中的HTML代码中发现这是一个 Found 响应 这意味着该请求被重定向到超链接中指定的地址 返回HTML代码是很明智的 这样如果一个浏览器因为某些原因不支持重定向的话 它可以把代码显示出来 或者在重定向过程中显示这些代码直到重定向完成 注意到超链接中包含了一个有趣的字符串 (l z psnhh cf oahmai p ) 显然 我们可以推断这就是的会话ID 它被嵌入了我们要重定向到的位置的URL中 在客户端代理中 我们需要做的仅仅是重新发送请求到这个新的URL 无须再在Win WinInet API编程中跋涉 我们可以直接找到proxy类的一个属性允许自动重定向 用外行人的说法 就是如果我们接收到一个 Found 响应 就直接将请求重新发送到相应中HTTP位置头所指示的URL 当Visual 的智能提示显示proxy类的AllowAutoRedirect属性时 我感到这东西真是机灵得可爱 我马上就在代码中加上如下一行   proxy AllowAutoRedirect = True我认为这仍然比创建一个CookieContainer类并关联到proxy类要容易得多 于是我又一次运行程序 很不幸 我遭遇了如下异常(为了简洁起见有所删节) An unhandled exception of type System InvalidOperationException occurred in system web services dllAdditional information: Client found response content type of text/; charset=utf but expected text/xml The request failed with the error message: …如果你看到错误消息的内容 你会发现你所看到的HTML页面跟你浏览 ASMX文件的页面一样 问题是 为什么当我传送XML(以SOAP封装了的形式)到Web Service服务器时它返回的却是HTML代码?结果证实 你并没有在SOAP封装中发送HTTP POST请求 而仅仅发送了一个简单的没有内容的HTTP GET请求 因此你的Web Service服务端理所当然地假设这个请求来自浏览器 于是它返回普通的HTML响应 为什么会这样呢?如果你了解HTTP协议 你会发现一个HTTP客户端在收到 Found 响应时发送HTTP GET请求到响应中指定的地址是合情合理的 即使初始请求是HTTP POST 这种方式下浏览器工作得很好 因为开始几乎所有的请求都是HTTP GET类型的 只有当你试图传递数据到一个URL时 才会出现上述失败的结果 理由是在传送的数据中可能包含潜在的敏感数据 因此你需要确认是否用户真的想向新的资源传送数据 显然如果你转向基于重定向设置的新地址 你就没能确认用户是否真的允许将他们的数据发送到新的地址 因此数据并没有被发送 而代之以简单的HTTP GET请求 我对代码做了如下修改 捕获 Found 异常 提示用户同意重定向他们的请求 然后再次在新的位置调用我的Web方法 同时使用基于Cookie和Cookie的SessionPrivate Cookies As System Net CookieContainerPrivate webServiceUrl as UriPrivate Sub Button _Click(ByVal sender As System Object _ByVal e As System EventArgs) Handles Button ClickDim proxy As New localhost Service ()Dim ret As Integer 设置proxy类的Cookie容器If Cookies Is Nothing ThenCookies = New System Net CookieContainer()End Ifproxy CookieContainer = Cookies 设置proxy类的URLIf webServiceUrl Is Nothing ThenwebServiceUrl = New Uri(proxy Url)Elseproxy Url = webServiceUrl AbsoluteUriEnd IfTryret = proxy IncrementSessionCounter()Catch we As WebException 如果我们想检测HTTP状态码 那么就需要一个HttpWebResponse类的实例If TypeOf we Response Is HttpWebResponse ThenDim HttpResponse As HttpWebResponseHttpResponse = we ResponseIf HttpResponse StatusCode = HttpStatusCode Found Then 这是一个 Found 响应 提示用户是否进行重定向If MsgBox(String Format(redirectPrompt _HttpResponse Headers( Location )) _MsgBoxStyle YesNo) = _MsgBoxResult Yes Then 用户选择Yes 重新尝试新的URLwebServiceUrl = New Uri(webServiceUrl _HttpResponse Headers( Location ))Button _Click(sender e)ReturnEnd IfEnd IfEnd IfThrow weEnd TryLabel Text = Result: & CStr(ret)End Sub现在的Session工作正常了 在你的应用程序中 你可以根据情况自行决定是否提示用户重定向HTTP POST请求 举一个例子 如果你正在调用一个Web Service 你也许就不希望出现任何可见的对话框 这样看来 要使的Session完全正常地工作还真不是很容易 但是 应该意识到上面的代码所展示的原理在其他情况下一样的有用 例如 任何平台上的任何Web Service 只要它使用HTTP cookie 都需要一个cookie容器 类似地 也许有很多其他的原因导致当你向一个Web Service服务器发送请求时收到 Found 响应 在一个复杂的应用程序中调用Web Service时 可能有许多特殊的情形需要你去处理 cookie和重定向的问题就是两种这样的情形 你应该将之作为你的Web Service调用代码中最基本的部分   结 论  在你调用Web方法的过程中 对状态保持是非常有用的 你必须意识到 当你使用手边的浏览器界面测试你的Web Service时 你并没有面对客户端程序必须处理的问题 幸运的是 这些问题并不是很难解决 cha138/Article/program/net/201311/12874

相关参考

知识大全 ASP.NET 3.5核心编程之AJAX Web Service的调用

ASP.NET3.5核心编程之AJAXWebService的调用  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起

知识大全 ASP.NET创建Web服务之管理Web服务状态

ASP.NET创建Web服务之管理Web服务状态  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 ASP.NET保持用户状态的九种选择(下)

ASP.NET保持用户状态的九种选择(下)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  ASP

知识大全 ASP.NET保持用户状态的九种选择(上)

ASP.NET保持用户状态的九种选择(上)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  摘要A

知识大全 ASP.NET服务器控件之视图状态

ASP.NET服务器控件之视图状态  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  为Web页面及

知识大全 在ASP.NET开发中使用非.Net Web服务

在ASP.NET开发中使用非.NetWeb服务  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!lis

知识大全 Asp.net中处理一个站点不同Web应用共享Session的问题

Asp.net中处理一个站点不同Web应用共享Session的问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一

知识大全 在ASP.NET AJAX的web应用中使用TODO服务

在ASP.NETAJAX的web应用中使用TODO服务  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 .NET Framework中使用XML Web Service

.NETFramework中使用XMLWebService  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 基于asp.net的web页面动态控件创建以及使用

 摘要web设计中有很多场合页面的控件要动态创建甚至只能动态创建这样可以增加页面的灵活性但是给程序员带来了一些麻烦比如要使用动态创建的控件怎么使用都是要求解决的问题本文基于aspnet简要介绍了页面的