2017-04-03 30 views
1

我已经阅读了许多关于该主题的文章,但找不到解决方案。 因此,请不要将此问题标记为重复,因为其他解决方案无法正常工作并且已经过时。在新的HttpWebRequest上共享当前会话

我有一个包含GridView的页面(每行一个按钮)的Web应用程序。 该按钮将创建一个HttpWebRequest(或WebClient,它是相同的)并获得它的HTML。

我试过使用一个cookie或所有的cookie,但我没有成功。 这是代码:

String path = Request.Url.GetLeftPart(UriPartial.Authority) + VirtualPathUtility.ToAbsolute("~/"); 

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(path + "MyPage.aspx"); 
CookieContainer cookieContainer = new CookieContainer(); 

HttpCookie httpCookie = HttpContext.Current.Request.Cookies.Get("ASP.NET_SessionId"); 
if (httpCookie != null) 
{ 
     Cookie myCookie = new Cookie(); 

     // Convert between the System.Net.Cookie to a System.Web.HttpCookie... 
     myCookie.Domain = webRequest.RequestUri.Host; 
     myCookie.Expires = httpCookie.Expires; 
     myCookie.Name = httpCookie.Name; 
     myCookie.Path = httpCookie.Path; 
     myCookie.Secure = httpCookie.Secure; 
     myCookie.Value = httpCookie.Value; 

     cookieContainer.Add(myCookie); 
} 

webRequest.CookieContainer = cookieContainer; 

string responseHTML = string.Empty; 
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse()) 
{ 
    using (Stream responseStream = response.GetResponseStream()) 
    { 
     using (StreamReader responseReader = new StreamReader(responseStream)) 
      { 
       responseHTML = responseReader.ReadToEnd(); 
      } 
     } 
} 

webRequest.GetResponse将得到超时。 我认为问题是域(localhost),我知道这是不可能的,但我没有任何域,我不会在web.config中创建一个假的域。此外,我尝试使用一个虚假的域名,但没有成功。

没有以下行

webRequest.CookieContainer = cookieContainer; 

它很好地工作,而不共享会话。 我记得域必须设置,否则我会收到相对错误。

回答

2

会话访问必须被序列化。当您使用ASP.NET会话时,有必要“序列化”HTTP请求以避免线程问题。如果两个或多个请求并行处理,这意味着两个线程可能同时更改或读取会话变量,这可能会导致各种问题。

好消息ASP.NET will serialize the requests for you, automatically。如果使用相同的ASP.NET_SessionId发送第二个请求,它将一直等到第一个请求完成。

坏消息:这意味着像你正在尝试的机制将无法正常工作。您的Web请求在一个正在进行的HTTP请求的上下文中运行;它会阻止任何额外的HTTP请求,直到它完成,包括您通过WebRequest发送的请求。

更多好消息:如果您的页面读取会话数据并且未写入会话数据,则可以指定一个允许两个线程同时运行的提示。尝试添加这两个页面(页面代码的背后是和你的代码试图访问的页面):

<% @Page EnableSessionState="ReadOnly" %> 

如果ASP.NET识别,本次会议的需求是只读的,它会允许两个只读线程同时使用相同的会话ID运行。

如果您需要在任一页面中进行读取/写入访问,那么您运气不好。

替代将代替使用HttpServerUtility.Transfer。第一页的角色会改变。它不是作为第二页的代理,而是将控制交给第二页。通过串联这些页面,可以避免任何并行性问题。

例子:

Server.Transfer("MyPage.aspx"); 
+0

很好的解决方案,但我需要在会话来写。第一页写道,第二页读。否则,我会使用查询字符串。该程序很旧,所以我试图不编辑一些页面。其他想法? @John Wu – Emanuele

+1

是的,[this](https://msdn.microsoft.com/en-us/library/caxa892w(v = vs.110).aspx)。 –

+0

我的代码在哪里? – Emanuele