views:

210

answers:

4

IIS6, ASP.NET 2.0, No Forms Authentication

I'm calling Response.Redirect("~/foo.aspx"), but the default document ("Default.aspx") for my site is appearing. To make matters worse, it only happens intermittently. Sometimes the redirect displays the right page.

I've checked session state, and I don't see any values in the web.config (that is, I'm assuming I'm using the 20-minute defaults).

I wish I had more relevant information to share (I'll do my best to answer any questions).

Any ideas? Why isn't it redirecting to the specified page?

EDIT: I've looked deeeeeper into the code and learned more details.

Ok. There's foo.aspx and foo2.aspx (and the default document, Default.aspx). All pages extend from BasePage, which extends Page.

BasePage has a property named ReturnPage:

protected string ReturnPage {
    get {
        if (Session["ReturnPage"] == null) {
            Session["ReturnPage"] = "";
        }
        return Session["ReturnPage"].ToString();
    }
    set { Session["ReturnPage"] = value; }
}

Users click on a LinkButton on foo.aspx, and the click event handler ends with two lines of code:

ReturnPage = ResolveUrl("~/foo.aspx");
Response.Redirect(ResolveUrl("~/foo2.aspx"));

The Page_Load of foo2.aspx has problems, and its error handling calls Response.Redirect(ReturnPage).

When I view the response headers of foo2.aspx, the 302 location is string.Empty (that is, there isn't one). That same response header has the same ASP.NET Session ID as the response of foo.aspx.

And remember -- this is intermittent. Sometimes, you can click on that LinkButton and go effortlessly to foo2.aspx, no problem. You can process the click with the exact same data once, and it will fail. You'll navigate from the default document (Default.aspx, where you were sent by the "bug") back to foo.aspx, click again with the same data (the same row in the grid/table -- the same LinkButton, essentially), and you'll be redirected to foo2.aspx without issue.

A: 

When you say:

Sometimes the redirect displays the right page.

Does it just happen, and you are not sure if there are certain pages that are affected by the problem? If this is the case, then you probably have a addressing problem. You can use either a relative path or an absolute path rather than an Application-relative path. I would also guess that you are trying to either direct to a page from a subdirectory on your site or to a subdirectory on your site. If you choose to stick with the Application-relative path make sure that are taking the subdirectory into account. (ex: ~/FooPages/Foo.aspx)

Here is a good reference page I just found: http://nathanaeljones.com/129/types-of-asp-net-paths/

AGoodDisplayName
See the details I've just added to the question. All of these pages are in the root of the site. I don't normally use ResolveUrl() when passing a value into Redirect(), but I can't help but think that, if this were a syntax problem, it wouldn't be happening intermittently.
lance
A: 

Once you redirect and get a new instance of the BasePage from foo2.aspx, won't that ReturnPage property be null again? Then once your page load errors out and tries to redirect it will be accessing a null string. Maybe try throwing that property in the Session

Session.Add("ReturnPage","~/foo.aspx") 

instead of

ReturnPage = ResolveUrl("~/foo.aspx");

Ofcourse you would have to modify that error handling in the page load to grab it out of session rather than the property and you may have to rethink how the whole redirect is working in your system if this turns out to be the issue.

EDIT: To test this idea about the property not getting set, or getting set correctly....(just to test I am not suggesting you should hard code the path in there), change your getter to the example below, then check to see if it works. Hope this helps, I am curious to find out what the problem is if this is not the issue.

get { 
   if (Session["ReturnPage"] == null) { 
        Session["ReturnPage"] = "~/foo.aspx"; 
    } 
    return Session["ReturnPage"].ToString(); 

} 
AGoodDisplayName
Unless I'm reading ReturnPage's getter and setter implementation wrong, it's setter *does* store the value (placed by foo.aspx) into the Session, and the foo2.aspx instance of BasePage *should* pull from the session, and return the value foo.aspx placed into the session (that is, it should *not* return empty string).
lance
I must have totally ignored what you had in code snippet, my apologies. However, according to the snippet, if it is null the getter is not going to do anything but return an empty string. I am making an edit to this answer.
AGoodDisplayName
A: 

I'm a little confused here. What exactly are you trying to accomplish? You're getting the default document exactly because the 302 is blank. Your "inconsistent" behavior is almost certainly due to the way you are saving data in the Session.

The real issue here is why you're redirecting when foo2.aspx "has problems". What's the problem here? Why redirect? If you really need to redirect, why is the redirect target changed? Make it a static error reporting page and you'll be fine.

Bryan
I've inherited the code. I don't care to defend it (quite the opposite at times), but I'd love to understand it, and I don't understand why the 302 is blank. The only explanation I can come up with is that the value that's put into the session by foo.aspx isn't there when foo2.aspx asks for it, and I can't understand what's causing the value to leave the session after it's placed there (again, by foo.aspx).
lance
+1  A: 

Placing a value in the session immediately before a Response.Redirect() is risky.

Changing foo.aspx's Response.Redirect() to the following might retain the session value more reliably:

Response.Redirect("~/foo2.aspx", false);
lance
Did this solve the problem?
Bryan
@Bryan: Priorities here haven't yet allowed me to test this. I'm eager to, and I will post results once I have.
lance