ASP.NET Redirect and End Page

2019-06-25 12:15发布

问题:

So I read up a lot about how to properly use Response.Redirect without causing some errors.

Response.Redirect(url, false);

Context.ApplicationInstance.CompleteRequest();

Situation: A user logs in the site and visits a page that lists forms. The user sits on that page for an hour doing nothing (which would log them out). The user clicks a button to edit a title (which requires a postback). This results in the user object being null since it logged him out of the session.

What I have done: In the page load, check if the user object is null and if it is, redirect to the login page. That is what should happen right?

Problem: The button event is STILL firing. Is it because I have the following line of code?

Context.ApplicationInstance.CompleteRequest();

How can I stop the event from being firing when I simply want to redirect to the login page?

I know I can provide true in the redirect code, but that will cause an error too right?

Response.Redirect(url, true);

What I currently do (which is not the best way I know): In the button event, I again check to see if the user object is null. If it is not null, proceed with the code to edit the title (recording who edited it). This is a bad way of handling this.

What I have seen: Wrap all events with Response.IsRequestBeingRedirected. But if I have several pages and lots of button events, this can get a bit annoying. Is this the only way to handle this situation?

Example:

protected void Page_Load(object sender, EventArgs e)
{
    Account account = Session["Account"] as Account;
    if (account == null)
    {
        Response.Redirect("WebForm1.aspx?NewSession=true", false);
        Context.ApplicationInstance.CompleteRequest();
        return;
    }
}

protected void Button1_Click(object sender, EventArgs e)
{
    Account account = Session["Account"] as Account;
    Label1.Text = account.userID.ToString();
}

Again, if I am already on the page, and the session expired, and I click Button1, the Button1_Click method is still being called. What I provided will give me a "NullReferenceException". Page_Load IS being called, and it is making the redirect. However, Button1_Click is still being called even with the return statement in Page_Load.

Thanks!

回答1:

You are correct about Response.Redirect(url, true). It is kind of expensive because it throws ThreadAbortException causing the current thread to terminate which is not what you want most of the times.

There is even a KB exists on this topic KB312629.

And yes, with your code it is not possible to prevent events from firing for the current IHttpHandler (which Page class implements) using built-in classes/methods.

So I would suggest to create base page class and add a bool field indicating about request completion request plus method that will call ApplicationInstance.CompleteRequest and will set the flag to true. Also you'll need to override RaisePostBackevent method to take control over controls (not Page) events invocation on page.

public abstract class BasePage : Page 
{
    private bool shouldNotRaiseEvents;

    protected void CompleteRequest() 
    {
        shouldNotRaiseEvents = true;
        Context.ApplicationInstance.CompleteRequest();
    }

    protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
    {
        if (shouldNotRaiseEvents) 
        {
            return;
        }
        base.RaisePostBackEvent(sourceControl, eventArgument);
    } 
}

Your updated code would be:

Response.Redirect(url, false);
CompleteRequest();

Also please note that if you have something inside LoadComplete, PreRender, SaveViewState, Render, Unload event handlers and you don't want this code to execute after redirect call you'll need to override that methods also.