System.Net.HttpWebRequest vs. System.Web.HttpRequest

K

Keith Patrick

Could someone explain to me the relationship between these two classes? I
am ripping my hair out trying to divert an HttpRequest to a new location via
an HttpWebRequest, but I cannot get my session xfer to work, possibly due to
the cookies not being compatible. I've spent over a week trying to get the
HWR to integrate nicely with my app, but I cannot get the session to
transfer, and it'd probably take me even longer if I tried to digest the
logic of having two parallel web request/response class hierarchies in the
BCL which don't seem to be compatible with one another. The
System.Net/System.Web dichotomy isn't making things any better, as *nothing*
I seem to work with, from credentials on down to cookies, works with the
current request, because each one has its own parallel set of support
classes. I'm currently using the following to move my cookies over, but it
obviously fails miserably (times out waiting to get a response from the
request):
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)
System.Net.HttpWebRequest.Create(uri.AbsoluteUri);

request.CookieContainer = new System.Net.CookieContainer();
request.CookieContainer.Add(HttpContext.Current.Request.Cookies);
foreach (String cookieName in
System.Web.HttpContext.Current.Request.Cookies) {
System.Web.HttpCookie cookie =
System.Web.HttpContext.Current.Request.Cookies[cookieName];
System.Net.Cookie bizarroCookie = new System.Net.Cookie();
bizarroCookie.Name = cookie.Name;
bizarroCookie.Value = cookie.Value;
bizarroCookie.Domain = uri.Host;
request.CookieContainer.Add(bizarroCookie);

}
 
S

Scott Allen

Hi Keith:

System.Web.HttpRequest is a class used on the server and inside an
ASP.NET application. It represents the *incoming* request from a
client.

System.Net.HttpWebRequest is a class used to make an *outgoing*
request to a web application.

I suspect your cookies won't transfer because the domains don't match.
Cookies are restricted to a domain. If the domain of a cookie is
www.microsoft.com, for example, you can't just send the cookie to the
server msdn.microsoft.com (but you could send a cookie with a domain
of .microsoft.com to both servers).
 
K

Keith Patrick

The domain from the HttpRequest is null (path is "/"), but if I copy those
over as-is, I get an argumentexception when I call
HttpWebRequest.CookieContainer.Add. What I'm doing now is setting Domain to
uri.Host while setting Cookie.Path = HttpCookie.Path. The response is
processed after a timeout (WebException, not TimeoutException), and it has 2
copies of each cookie, all of them having a null Domain and "/" for path.
The double set of cookies is only being problematic - the timeouts - when
the ASP.Net_SessionId cookie is copied over. I'm hoping to get some kind of
understanding as to the cookie/session mechanism a bit better than the
standard articles (without reading IL :) ) to where I can figure out why the
copies of cookies are coming over, and why the copied session cookie is
leading to the thread hanging until timeout.

Scott Allen said:
Hi Keith:

System.Web.HttpRequest is a class used on the server and inside an
ASP.NET application. It represents the *incoming* request from a
client.

System.Net.HttpWebRequest is a class used to make an *outgoing*
request to a web application.

I suspect your cookies won't transfer because the domains don't match.
Cookies are restricted to a domain. If the domain of a cookie is
www.microsoft.com, for example, you can't just send the cookie to the
server msdn.microsoft.com (but you could send a cookie with a domain
of .microsoft.com to both servers).

--
Scott
http://www.OdeToCode.com/blogs/scott/

Could someone explain to me the relationship between these two classes? I
am ripping my hair out trying to divert an HttpRequest to a new location
via
an HttpWebRequest, but I cannot get my session xfer to work, possibly due
to
the cookies not being compatible. I've spent over a week trying to get
the
HWR to integrate nicely with my app, but I cannot get the session to
transfer, and it'd probably take me even longer if I tried to digest the
logic of having two parallel web request/response class hierarchies in the
BCL which don't seem to be compatible with one another. The
System.Net/System.Web dichotomy isn't making things any better, as
*nothing*
I seem to work with, from credentials on down to cookies, works with the
current request, because each one has its own parallel set of support
classes. I'm currently using the following to move my cookies over, but
it
obviously fails miserably (times out waiting to get a response from the
request):
System.Net.HttpWebRequest request =
(System.Net.HttpWebRequest)
System.Net.HttpWebRequest.Create(uri.AbsoluteUri);

request.CookieContainer = new System.Net.CookieContainer();

request.CookieContainer.Add(HttpContext.Current.Request.Cookies);
foreach (String cookieName in
System.Web.HttpContext.Current.Request.Cookies) {
System.Web.HttpCookie cookie =
System.Web.HttpContext.Current.Request.Cookies[cookieName];
System.Net.Cookie bizarroCookie = new System.Net.Cookie();
bizarroCookie.Name = cookie.Name;
bizarroCookie.Value = cookie.Value;
bizarroCookie.Domain = uri.Host;
request.CookieContainer.Add(bizarroCookie);

}
 
S

Scott Allen

Hi Keith:

Even if you managed to get the Session cookie copied over - it
wouldn't make sense when it arrives at a different server or even on
the same server in a different ASP.NET application. Session is per
application and application A has no knowledge or ability to map
session information in application B.
 
K

Keith Patrick

This is the same application. I'm just trying to POST data that has get
GET'ed in a session that has already been authenticated. It's something
that's been asked quite a bit and answered in various forms, but I have yet
to find someone who has done it in an already-authenticated application. I
*do* get the session information transferred over with the double cookies,
but it only happens after the timeout has occurred, so somehow the session
cookie (or the fact that there are two of them) is causing the request (or a
request) to stall HttpWebRequest.GetResponse. But once that WebException is
thrown, my breakpoint in the target page gets hit.
 
S

Scott Allen

Oh - in the same application? I'm pretty sure ASP.NET serializes
requests coming in with the same SessionID - so your second web
request will never have a chance to execute.

Have you considered Server.Transfer or Server.Execute? These would
make for an easier approach.
 
K

Keith Patrick

Server.Transfer does not allow for data to be POSTed, does it? I originally
used that method (incidentally, is it me, or does neither MSDN or many
articles seem to actually say how Transfer and Execute differ?), but the
only way I could send the data I needed to send from one page to the other
was via Context.Items, but that mechanism breaks down when you start doing
things like hitting Back or Refresh (my data cannot be placed in a
QueryString because it exceeds the max URL length)
 
K

Keith Patrick

Ahhh, I see that I can get it to work. I'd tried setting preserveForm to
true before, but never had any luck. Turns out, I *can* get those
variables, but their names are a mess. Basically, we have a usercontrol
called "ReportLink" that has certain dependency controls, like YearSelector.
The YearSelector value was given its own querystring key in ReportLink's
code, which is why I could not make sense of preserveForm.

One problem with this, though, that I need to figure out: The usercontrol
owns the yearselector control, so when the target page gets the page, I have
to somehow know that the value in the Request.Form is
"NewSummary_YearSelector:yearList" instead of just "yearList".
 
S

Scott Allen

Right - you can't post but just pass data along and the client is none
the wiser because it doesn't know you are executing a different page -
so I suppose it can cause navigation problems.

It's hard to know what the best solution is for you without seeing the
whole application, but ultimately it sounds like you need to execute
some code in another page. I don't know if the other code updates a
database or displays information in the form - but you might consider
breaking the code out into a separate class that you can use from any
page in the application, or into a user control if the other code
involves displaying a UI.
 
S

Scott Allen

Ahhh, I see that I can get it to work. I'd tried setting preserveForm to
true before, but never had any luck. Turns out, I *can* get those
variables, but their names are a mess. Basically, we have a usercontrol
called "ReportLink" that has certain dependency controls, like YearSelector.
The YearSelector value was given its own querystring key in ReportLink's
code, which is why I could not make sense of preserveForm.

One problem with this, though, that I need to figure out: The usercontrol
owns the yearselector control, so when the target page gets the page, I have
to somehow know that the value in the Request.Form is
"NewSummary_YearSelector:yearList" instead of just "yearList".

A more robust approach would be to give the user control a public
property that you can read to get the value for year. Karl has some
excellent tips along these lines in his article:
http://www.openmymind.net/communication/index.html Any other approach
might be broken if the ID prefix ever changes (the piece before the
colon).

Am I making sense?
 
K

Keith Patrick

I've already got that part, but how would I send that year to the target of
Server.Transfer? When I do a Server.Transfer, I'm on a page that does not
contain the usercontrol that had all the values. All I've got now are the
values POSTed to the Request.Forms collection, and those are all UniqueIDs
(although I could pass mapping information in the querystring to map
recognized key name to the unique ID, it's yet another hack to get around
the lack of true POSTing functionality). If there's some way for the
Transfer target to access the sender's Controls collection, that'd be great,
but I'm not seeing it. And it actually still wouldn't be ideal, as we use
Request["MyParam"] in hundreds of locations.
 
S

Scott Allen

Well, here is another technique.

You can get to the original page - it is in the Context.Handler
property which represents the original "handler" for the HTTP request.
In other words, ASP.NET has a contract where every HTTP request
reaching ASP.NET has to be handled by an object implementing
IHttpHandler. In the case of a request reaching an ASPX page, the web
form (derived from System.Web.UI.Page) is the handler.

The Page_Load for the second page (the destination of Server.Transfer)
could look something like:

void Page_Load()
{
if (!IsPostBack)
{
OriginalPage oc;
oc = Context.Handler as OriginalPage;

// now you have a reference to the first web form
if(oc != null)
{
// assuming user control is a property...
int year = oc.YearSelectControl.Year;
}
}
}

You could also use FindControl to get a reference to the user control
with the year select. Request is a bit fragile, especially when it
comes to user controls which change the key names.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top