While performing a response.redirect in an ASP.NET page, I received the error:
error: cannot obtain value
for two of the variables being passed in (one value being retrieved from the querystring, the other from viewstate)
I've never seen this error before, so I did some investigating and found recommendations to use the "False" value for "endResponse"
e.g. Response.Redirect("mypage.aspx", False)
This worked.
My question is: what are the side-effects of using "False" for the "endResponse" value in a response.redirect?
i.e. are there any effects on the server's cache? Does the page remain resident in memory for a period? Will it affect different users viewing the same page? etc.
Thanks!
From this other question and this blog post, the recommended pattern is-
Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();
This avoids the expensive ThreadAbortException/Response.End. Some code will be executed after the CompleteRequest(), but ASP.Net will close the request as soon as it is convenient.
Edit- I think this answer gives the best overview. Note that if you use the pattern above, code after the redirect will still be executed.
An MSDN blog post that might answer your question:
The drawback to using [Response.Redirect(url, false)] is that the page will continue to process on the server and be sent to the client. If you are doing a redirect in Page_Init (or like) and call Response.Redirect(url, false) the page will only redirect once the current page is done executing. This means that any server side processing you are performing on that page WILL get executed.
Response.Redirect(..., true) results in a ThreadAbortException.
depending on your exception handling setup you might get your log filled with error messages one for each redirect.
Related
When implementing the post-redirect-get pattern in a web application, it is common for the final step in your server code to look something like this (pseudocode):
if (postSuccessful)
{
redirect("/some-page?success=true")
}
That is, the redirect URL has some kind of success parameter in the query string so that you know when to display a nice looking "Your form has been submitted!" message on your page. The problem with this is that the success=true persists in the query string when it's only needed to initialize the page. If the user refreshes the page or bookmarks it, they will receive a false success message even though no additional POST has taken place.
Is there an elegant solution to this that doesn't involve using JavaScript to eliminate success=true from both the query string and the browser history? This solution works, but definitely adds complexity to a page's load process.
You can use server side technology to implement this feature, without any JavaScript. The stes are listed below:
When post is successful, redirect to /some-page with current timestamp information:
if (postSuccessful)
{
redirect("/some-page?success=true×tamp=1559859090747")
}
When server receives GET /some-page?success=true×tamp=1559859090747 request, compare the timestamp parameter with the current timestamp, check whether it is within the last 3 seconds (or you can change this number according to the network environment).
If the timestamp parameter is within last 3 seconds, then it means this GET /some-page?success=true request is a result of server redirect. If not, then it's more like a result of "user refreshes the page or bookmarks it".
In server code that handling GET /some-page, render different HTML according to the result of step 3. Display the success message only when current access is a result of server redirect.
I am a bit new to VB.NET. I have a page that sets 2 session variables and does a redirect to second page. The second pages is at least using one of the session variables. I can tell because on the second page, if the session variable is not correct the user is redirected to an access denied page. The second page also uses the session variable in question. It will read it an fill a gridview based on the value of the variable. I set the variable like so
Session("ID") = Convert.ToInt32(a_value)
and on the second page I retrieve the variable like this
a_page_variable = Session("ID")
What I find strange is that when I run this code in visual studio it works as expected but when I deploy and run it, I get 0 from my session variable instead of the true value of "a_value". I have tried a few things like making sure the data types match up from page to page and trying different ways to retrieve the variable such as
Session("userID")
and
CType(Session.Item("userID"), Int32)
I've also tried to see what is coming in to the second page by using
Response.Write
I also tried to use SQL Profiler to see what kind of call is being made to fill the gridview but I haven't had any luck. The gridview gives me an empty dataset and the Profiler does not detect a call being made from the application. I thought working with session variables was pretty straight forward but obviously, I am missing something.
Thanks for your help,
Billy
One possibility (and the only one that could be guessed at with how little information we have) could be the response.redirect causing the application to terminate due to an exception.
When redirecting, you want to always pass a false, and then call complete request.
Response.Redirect(urlstring, False)
Response.CompleteRequest()
not following these steps can cause exceptions, which may drop session.
Additionally, resolve virtual paths, as some browsers (mobile especially) can see those redirects as new requests entirely, thus generating new session tokens.
Dim urlstring As String
urlstring = Page.ResolveUrl("~/default.aspx")
that said, there are a number of possible causes for this situation.
Application Pool restarts
App Domain restarted
Code changing value unexpectedly
AV tinkering with files
deployed to web farm
With the description provided above, we just don't have enough information to really troubleshoot.
Thank you ADyson, Stephen Wrighton and everyone else who took a stab at helping me figure this out. I was able to find out what was going on by adding code that wrote to a log file on the server. Found the logging code here. I found that I never reached the code that set the session variable and that is the reason it never populated on the second page. I was trying to get the logon name for the user by using Environment.UserName which will return the user name of the person who is currently logged on to the operating system. But what I really wanted to do was get the logon name of the user that was visiting my site. For this I used User.Identity.Name. This works great when you need to know which user from an Active Directory domain is visiting your site.
In Response.redirect ("Page.aspx",bool end response), How do I transfer the page and come back to to the same execution point?
I mean to say how can I use the bool value for my programming purpose.
Please let me know
If i understand "come back to the same execution point" correctly, you might consider using Server.Execute instead.
From MSDN
Executes the handler for a specified resource in the context of the
current request and returns execution to the page that invoked it.
I think you can create a session variable and stock the "starting point"(url) in the variable.
After that you can get the "starting point" from anywhere and go back to this page..
(If it is want you want to do..)
You could to start run all your operation in another thread and then only do response.redirect("someurl"), i.e.
reponse.redirect("some.aspx");
myoperation();
myoperation1();
replace this code on
ThreadPool.QueueUserWorkItem(delegate
{
myoperation();
myoperation1();
});
Response.Redirect("some.aspx");
To answer your specific questions:
you cannot use the bool parameter for your own purposes - it is there to signal whether to end the response back to the client (msdn link)
when you redirect or transfer to a page you still need to go through the page life cycle, you cannot just start at some arbitrary bit of code on the page. As already mentioned in the answer from InSane, use the Execute method instead.
2nd in an occasional series:
Here's the first one
Is CAT.NET correct that the following is a genuine vulnerability in ASP.NET or is it a false positive?
var myInt = Int32.Parse(txtUserInput.Text);
Response.Redirect(string.Format("myPage.aspx?myId={0}", myInt);
CAT.NET is reporting this as a redirect vulnerability needing remediation via encoding myInt.
I wouldn't call that dangerous but its not how I would write it myself
int myInt;
if(Int32.TryParse(txtUserInput.Text,out myInt)){
Response.Redirect(string.Format("myPage.aspx?myId={0}", myInt);
}
Is to my mind cleaner as it wont throw an exception if the parse fails due to bad user input and we are explicitly typing the int.
Any error handling code can be bundled into an else statement on the end.
I don't believe so, it could cause an exception so TryParse might be a better approach. It's just yelling because you are taking user input and redirecting based on it. It's possibly being a little too aggressive which isn't exactly bad.
There is no exploitable vulnerability as a result of this code. Any vulnerability would be a result of what myPage.aspx does with the value of myId, not how your url is built. Anyone could just as easily directly hit myPage.aspx with anything they want in the querystring.
However this is bad practice, assuming that you haven't left anything out of the code between those two lines. You should verify that txtUserInput.Text contains only numeric characters, and falls within allowable values.
Exploits happen because of improper parsing of user-supplied data by the page it's posted to -- not improper generating of URLs. While it's a good idea to try to make sure your web site won't write a broken URL because of something that's put in a form, input validation at the front-end is irrelevant to security. All that matters is what the code that accepts the input does with it, since any post or query string can be forged.
I have Default.aspx page, which inherits from BasePage.cs, which inherits from System.Web.UI.Page. BasePage is where I do some common things every page must do upon loading.
In BasePage, lets say I'm checking for X. If X=1, then I will redirect to my "Discontinued.aspx" page immediately and stop execution of BasePage. If I find X=1, I say:
HttpContext.Current.Response.Redirect("Discontinued.aspx", true);
I want the redirect to stop execution of BasePage and immediately jump out - hence the "true" in the above statement - which should stop execution of the current page as I understand. The problem is, it doesn't. I'm expecting the redirect to throw the "thread abort exception".
When I run in debug mode, it contines stepping through as though it didn't just redirect and leave.
But the redirect was still started as well - once I get done stepping through the rest of BasePage, the "Discontinued" page then begins to load as a result of the redirect.
Is there a reason my Redirect will not kill execution of BasePage?
The second parameter for Response.Redirect is endResponse, however the tooltip says 'Indicates whether execution of the current page should terminate'. This is misleading, because the execution of the page does not actually terminate when the variable is true. It will finish running any code. However what does happen differently, is the Render events are canceled, and the Response is immediately flushed with the object moved header.
You need to manually exit out of any methods, Response.Redirect / Response.End will not do that for you. Futhermore, if you need a conditional to see if the Page has been redirected, check out Response.IsRequestBeingRedirected.
are you exiting from the function that calls redirect, e.g.
...redirect(stopit,true);
return;
?
Probably you are calling the Response.Redirect method inside a try{}catch{} block, try it by calling outside of this block and you'll see that it will not fail.
More info:
http://www.velocityreviews.com/forums/t72105-responseredirect-in-a-trycatch.html
Hope this helps.
You can throw an exception, that will exit code execution, but still redirect:
HttpContext.Current.Response.Redirect("/login", true);
throw new Exception("Unauthorized Access");
I'm going to get down voted for this! Curse my ignorance...
Obviously you could try adding the following line after the redirect (as pointed out by recursive),
response.end()
But maybe the reason the response.redirect is not immediately causing redirection is that you have response buffering on (the default) and the page processing is not ended until after the buffer is flushed. If this were true (and admittedly I'm to lazy too try) then adding the following line would also solve you problem.
response.flush()
For an unconditional termination, you could try a
Response.End()