2

I have already read many articles about the topic but I can't find solution. So please don't mark this question as duplicate because other solutions won't work and are out to date.

I have a web application with a page containing a GridView (one button per row). The button will create a HttpWebRequest (or WebClient, it's the same) and get its html.

I tried using one cookie or all the cookies but I have no success. This is the code:

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 will get timeout. I think the problem is the domain (localhost), i know it's not possible but i have not any domain and i won't create a fake one in web.config. Moreover i have tried using a fake domain without success.

Without the following line

webRequest.CookieContainer = cookieContainer;

it works nicely without sharing session. I would remember domain must be set otherwise i will received the relative error.

Emanuele
  • 648
  • 12
  • 33

1 Answers1

2

Session access must be serialized. When you use ASP.NET session, it is necessary to "serialize" HTTP requests to avoid threading issues. If two or more requests were processed in parallel, that would mean two threads could change or read session variables at the same time, which could cause a variety of issues.

The good news: ASP.NET will serialize the requests for you, automatically. If you send a second request with the same ASP.NET_SessionId, it will wait until the first one has completed.

The bad news: That means that a mechanism like the one you are attempting will not work. Your web request runs in the context of one HTTP request that is already in progress; it will block any additional HTTP requests until it is completed, including the request that you are sending via WebRequest.

More good news: If your page reads session data and does not write it, it can specify a hint that will allow two threads to run concurrently. Try adding this to both pages (the page your code is behind and the page that your code is attempting to access):

<% @Page EnableSessionState="ReadOnly" %>

If ASP.NET recognizes that the session needs are read-only, it'll allow two read-only threads to run at the same time with the same session ID.

If you need read/write access in either page, you are out of luck.

An alternative would be to use HttpServerUtility.Transfer instead. The role of the first page would change. Instead of serving as a proxy to the second page, it hands off control to the second page. By putting the pages in series, you avoid any issues with parallelism.

Example:

Server.Transfer("MyPage.aspx");
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • Nice solution but i need to write in session. First page writes, the second reads. Otherwise i'd have used querystring. The program is very old so I'm trying to not edit some pages. Other ideas? @John Wu – Emanuele Apr 04 '17 at 07:28
  • 1
    A call to `HttpServerUtility.Transfer` would replace the entirety of the code shown in your example. – John Wu Apr 04 '17 at 09:32
  • Have you read "The button will create a HttpWebRequest (or WebClient, it's the same) and get its html."? – Emanuele Apr 04 '17 at 09:35
  • The requirement is for the HTML from the second page to be returned to the browser, right? So instead of creating a WebClient to get the HTML from the second page, you merely transfer control to it, and allow it to return the HTML directly. – John Wu Apr 04 '17 at 09:38
  • So try to give a solution with a code sample. Thanks – Emanuele Apr 04 '17 at 09:43