2

Trying to follow best practice for Response.Redirect

Response.Redirect(someURl, false);
Context.ApplicationInstance.CompleteRequest();

As described in this MSDN blog: correct-use-of-system-web-httpresponse-redirect Which basically says:

Use the CompleteRequest overload that does not cause a thread abort exception.

The MSDN page for CompleteRequest says:

Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.

However all page events after calling CompleteRequest still fire. So no code is skipped. This appears to contradict the MSDN documentation. Is there a workaround? Have i misunderstood the documentation?

(The blog post does say the skip is at page level but the API documentation does not say this. I'm guessing the answer will just be the documentation is misleading.)

You can test by debug stepping quite a simple page:

<asp:CheckBox ID="CheckBox0" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:CheckBox ID="CheckBox1" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:CheckBox ID="CheckBox2" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:CheckBox ID="CheckBox3" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:Button ID="btnRedirect" runat="server" Text="Click Me" OnClick="btnRedirect_Click" />
<asp:Label ID="lblNotes" runat="server" />

Code:

protected void Page_Load(object sender, EventArgs e)
{
    lblNotes.Text += " Load " + DateTime.Now.ToString();
}

protected void Page_PreRender(object sender, EventArgs e)
{
    lblNotes.Text += " PreRender " + DateTime.Now.ToString();
}

protected void chk_CheckedChanged(object sender, EventArgs e)
{
    Response.Redirect("stackoverflow.com", false);
    Context.ApplicationInstance.CompleteRequest();
}

protected void btnRedirect_Click(object sender, EventArgs e)
{
    lblNotes.Text += " Btn " + DateTime.Now.ToString();
}

If you check all the tick boxes then press the button many events are fired.

Bucket
  • 514
  • 6
  • 10
  • By using false in Response.Redirect it ends further execution of current thread. So it may cause issue in some case. – Ravikumar Aug 17 '17 at 10:41
  • @Ravikumar Otherway round i think. Using True in Response.Redirect ends further execution of current thread which raises a ThreadAbort exception. Which is what i'm trying to avoid. That's why I'm passing false. – Bucket Aug 17 '17 at 10:49
  • Can you share more code or your complete execution thread. – Ravikumar Aug 17 '17 at 10:53

1 Answers1

2

It seems that you are thinking that the CompleteRequest() method will terminate the execution of the page similar to Response.Redirect(url, true). However, as explained by John S Reid in this article, the CompleteRequest will only end the application events that occur after the page execution step in the ASP.NET Application Life Cycle, which may change according to the version of ASP.NET.

The page will still process postback events and render the page, but the above article has an example on how to prevent that if you are interested in an example.

Below is what the code might look like for your example:

private m_bIsTerminating = false;

protected void chk_CheckedChanged(object sender, EventArgs e)
{
    Response.Redirect("Default2.aspx", false);
    Context.ApplicationInstance.CompleteRequest();
    m_bIsTerminating = true;
}

protected void btnRedirect_Click(object sender, EventArgs e)
{
    lblNotes.Text = "button click event";
}

protected override void RaisePostBackEvent(IPostBackEventHandler 
    sourceControl, string eventArgument)
{
    if (m_bIsTerminating == false)
    base.RaisePostBackEvent(sourceControl, eventArgument);
}

protected override void Render(HtmlTextWriter writer)
{
    if (m_bIsTerminating == false)
    base.Render(writer);
}

If you were to debug after checking the boxes and clicking the button, the checkboxes will raise a postback event and then a render, both of which will not be called. Then the button click event will not be processed and the redirect occurs.

Also, I found this stackoverflow post which is similar to this question and goes over a some more information pertaining to the CompleteRequest() method.

Kyle Scott
  • 64
  • 4
  • Was not expecting it to terminate execution i was just expecting unprocessed postback event's not to fire after calling CompleteRequest as that's what the MSDN documentation implies will happen. My issue is the behavior does not match the documentation. – Bucket Aug 18 '17 at 10:00
  • That article does indeed provide a workaround using overrides to RaisePostBackEvent and Render. Please post an answer including that part of the content and a link to the original article. I'll then mark that as the accepted answer. – Bucket Aug 18 '17 at 10:15
  • The "John S Reid" workaround *only* covers the situation where the redirect is raised inside the Page_Load. Unfortunately if the redirect is done in a postback event it does not stop all other events from firing. – Bucket Aug 18 '17 at 11:09
  • I added an example on how to override the postback event/render inside the checkedchanged event. Hopefully that gives you an idea of how to go about it somewhere other than the Page_Load. Also, that is John S. Reid's company website so that should be the original article. – Kyle Scott Aug 18 '17 at 15:35