转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 站长学院 >> Web开发 >> 正文
Using ASP.NET Session State in a Web Service         ★★★★

Using ASP.NET Session State in a Web Service

作者:闵涛 文章来源:闵涛的学习笔记 点击数:3061 更新时间:2009/4/23 10:43:17
'''' Does NOT work with ASP.NET Sessions
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim proxy As New localhost.Service1()
Dim ret As Integer
ret = proxy.IncrementSessionCounter()
Label1.Text = "Result: " & CStr(ret)
End Sub

When I invoke the Web service the first time, everything works as expected. The Web method returns the initial value for my session variable, which is 1. Now if I click on Button1 to invoke my Web method again, I expect to see a returned value of 2. However, no matter how many times I click on Button1, I always see a value of 1 returned.

You might suspect the cause of this is that I''''m creating a new instance of the proxy class for my Web service, so each time I click on the button, I am losing my cookies (so to speak). Unfortunately, even if you move the proxy initialization code into the constructor for your Form class and use the same instance of the proxy for each Web method call, you still will not see the session variable return with a value greater than 1.

The problem is with the cookies. The Web service code does not see a valid session ID with the request, so it creates a brand new HttpSessionState object for each call, and returns the initial value of 1. The reason for this is that the client proxy class, which inherits from the System.Web.Services.Protocols.SoapHttpClientProtocol class does not have an instance of the System.Net.CookieContainer class associated with it. Basically, there is no place to store cookies that are returned. To fix this problem, I changed my code as follows with the new code highlighted:

'''' Works with cookied ASP.NET sessions but NOT with 
'''' cookieless sessions.
Private Cookies As System.Net.CookieContainer

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim proxy As New localhost.Service1()
Dim ret As Integer
'''' Set the Cookie Container on the proxy
If Cookies Is Nothing Then
Cookies = New System.Net.CookieContainer()
End If
proxy.CookieContainer = Cookies
ret = proxy.IncrementSessionCounter()
Label1.Text = "Result: " & CStr(ret)
End Sub

And now the code works as expected! With each click of Button1, I see the returned value increase by 1. Note that the Cookies variable is not declared inside my function. It is a private member of my form class. I need to use the same instance of the CookieContainer class with each request if I expect the same session ID cookie to be returned to the server. This explains why a default cookie container is not automatically associated with an instance of the SoapHttpClientProtocol class. There is a good chance that you would want to use a separately managed cookie container that could be shared among multiple instances of the SoapHttpClientProtocol class, instead of automatically creating a new cookie container for each instance.

Cookieless Sessions

From the standpoint of the Web service developer, you might think that quite a few people trying to consume your service will forget to add a cookie container to their client proxies. With a clever twinkle in your eye, you also might think that cookieless sessions may be the perfect solution to this problem. If you set the cookieless attribute of the sessionState element to "true" in your web.config, you will notice that sessions still work perfectly when invoking your Web methods using the browser interface. Unfortunately, there are still issues if you use the "Add Web Reference" capabilities within Visual Studio .NET.

To investigate cookieless sessions, I decided to take the client code I used above and simply see if it would work for a Web service that was configured for cookieless sessions. I did not bother to delete the cookie container code, because I wanted to have code that would work with traditional cookied sessions as well as cookieless sessions. Being a bit of an optimist, I simply ran the code as is. Disappointingly, but not completely unexpectedly, I witnessed the following exception:

An unhandled exception of type ''''System.Net.WebException'''' occurred in system.web.services.dll

Additional information: The request failed with the error message:
--
<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href=''''/HttpSessionState/(l2z3psnhh2cf1oahmai44p21)/service1.asmx''''>here</a>.</h2>
</body></html>

What happened is that the HTTP request received a response that was not a "200 OK" HTTP response. For those of you familiar with HTTP, you probably can correlate the HTML listed in the response shown as indicating that this was a "302 Found" HTTP response. This means that the request was redirected to the URL indicated in the hyperlink. The HTML returned is actually just a nice thing that a browser can show if for some reason it does not support redirects, or until the redirected request completes. If you look at the hyperlink, you will notice that the href includes an interesting substring of "(l2z3psnhh2cf1oahmai44p21)". If you have been paying attention, you have probably correctly deduced that this is the ASP.NET session ID, and it has been embedded in the URL that we have been redirected to. What we need is for our client proxy class to resend the request to this new URL.

Having done more than my share of programming with the old Win32 WinInet API, I went looking for a property on our proxy class that would allow me to turn on auto redirects. In layman''''s terms, this simply means that if we received an HTTP response of "302 Found," we would simply resend the request to the URL indicated by the HTTP Location header in the response. I was feeling pretty smart when the Microsoft® IntelliSense® in Visual Studio .NET showed me the AllowAutoRedirect property on my proxy class. I quickly added the following line to my code:

proxy.AllowAutoRedirect = True

I gave my program another try, thinking this was still slightly easier than creating a CookieContainer class, and assigning it to my proxy. I got the following exception (truncated for brevity):

An unhandled exception of type ''''System.InvalidOperationException'''' occurred 
in system.web.services.dll

Additional information: Client found response content type of ''''text/html; charset=utf-8'''',
but expected ''''text/xml''''.

The request failed with the error message: …

If you looked at the contents of the error message, you would find that you were looking at the HTML page that you see when you browse to your .ASMX file. The question you might have is: Why it is returning HTML when I am posting XML (in the form of a SOAP envelope) to the Web service? As it turns out, you did not send an HTTP POST request with a SOAP envelope, you simply sent an HTTP GET request with no body, and your Web service appropriately assumed you were a browser and returned its normal HTML response. How could this happen?

If you read the HTTP specification, you will find that it is appropriate for an HTTP client to send an HTTP GET request to the indicated URL in reaction to an HTTP "302 Found" response, even if the initial request was an HTTP POST. This works great with browsers, because just about all of their requests are HTTP GET requests in the first place. It does not work well when you see this result when you are posting data to a URL.

The justification for this is that potentially sensitive data may be contained in the posted data, so you need to confirm with the user if they really want to send the data to the new resource. If you are going to the new location based off an auto-redirect setting, you are obviously failing to confirm with the user whether it is okay to post their data to a new location. Therefore the data is not sent, and a simple HTTP GET request is sent instead.

I made the following modifications to set the URI on the proxy, catch the "302 Found" WebException, prompt the user for permission to redirect their request, and call my function again with the new location (changes from the previous code are highlighted):

'''' Works with both cookied and cookieless ASP.NET sessions.
Private Cookies As System.Net.CookieContainer
Private webServiceUrl as Uri

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim proxy As New localhost.Service1()
Dim ret As Integer
'''' Set the Cookie Container on the proxy
If Cookies Is Nothing Then
Cookies = New System.Net.CookieContainer()
End If
proxy.CookieContainer = Cookies
'''' Set the Url on the proxy
If webServiceUrl Is Nothing Then
webServiceUrl = New Uri(proxy.Url)
Else
proxy.Url = webServiceUrl.AbsoluteUri
End If

上一页  [1] [2] [3]  下一页


[Web开发]详细介绍session的用法详解  [系统软件]Using dllimport and dllexport in C++ Classes
[VB.NET程序]How to setup a basic Struts project using Ecli…  [Web开发]Ajax using XMLHttpRequest and Struts
[Web开发]参数传递解决window.open的session变量丢失  [Web开发]php实现多session并发运行
[Web开发]彻底放弃IIS让Apache也支持ASP.NET  [Web开发]ASP.NET 2.0发送电子邮件中存在的问题
[Web开发]ASP.NET 2.0移动开发之属性重写和模板化  [Web开发]ASP.NET 2.0中实现模板中的数据绑定
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Web开发  · 网页制作
    · 平面设计  · 网站运营
    · 网站推广  · 搜索优化
    · 建站心得  · 站长故事
    · 互联动态
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台