Is Response.End() considered harmful?

Viewed 91148

This KB Article says that ASP.NET's Response.End() aborts a thread.

Reflector shows that it looks like this:

public void End()
{
    if (this._context.IsInCancellablePeriod)
    {
        InternalSecurityPermissions.ControlThread.Assert();
        Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
    }
    else if (!this._flushing)
    {
        this.Flush();
        this._ended = true;
        if (this._context.ApplicationInstance != null)
        {
            this._context.ApplicationInstance.CompleteRequest();
        }
    }
}

This seems pretty harsh to me. As the KB article says, any code in the app following Response.End() will not be executed, and that violates the principle of least astonishment. It's almost like Application.Exit() in a WinForms app. The thread abort exception caused by Response.End() is not catchable, so surrounding the code in a try...finally won't satisfy.

It makes me wonder if I should always avoid Response.End().

Can anyone suggest, when should I use Response.End(), when Response.Close() and when HttpContext.Current.ApplicationInstance.CompleteRequest()?

ref: Rick Strahl's blog entry.


Based on the input I've received, my answer is, Yes, Response.End is harmful, but it is useful in some limited cases.

  • use Response.End() as an uncatchable throw, to immediately terminate the HttpResponse in exceptional conditions. Can be useful during debugging also. Avoid Response.End() to complete routine responses.
  • use Response.Close() to immediately close the connection with the client. Per this MSDN blog post, this method is not intended for normal HTTP request processing. It’s highly unlikely that you would have a good reason to call this method.
  • use CompleteRequest() to end a normal request. CompleteRequest causes the ASP.NET pipeline to jump ahead to the EndRequest event, after the current HttpApplication event completes. So if you call CompleteRequest, then write something more to the response, the write will be sent to the client.

Edit - 13 April 2011

Further clarity is available here:

9 Answers

If you had employed an exception logger on your app, it will be watered down with the ThreadAbortExceptions from these benign Response.End() calls. I think this is Microsoft's way of saying "Knock it off!".

I would only use Response.End() if there was some exceptional condition and no other action was possible. Maybe then, logging this exception might actually indicate a warning.

I disagree with the statement "Response.End is harmful". It's definitely not harmful. Response.End does what it says; it ends execution of the page. Using reflector to see how it was implemented should only be viewed as instructive.


My 2cent Recommendation
AVOID using Response.End() as control flow.
DO use Response.End() if you need to stop request execution and be aware that (typically)* no code will execute past that point.


* Response.End() and ThreadAbortExceptions.

Response.End() throws a ThreadAbortException as part of it's current implementation (as noted by OP).

ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block.

To see how to write code that must deal with ThreadAbortExceptions, see @Mehrdad's reply to SO How can I detect a threadabortexception in a finally block where he references RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup Method and Constrained Execution Regions


The Rick Strahl article mentioned is instructive, and make sure to read the comments as well. Note that Strahl's issue was specific. He wanted to get the data to the client (an image) and then process hit-tracking database update that didn't slow down the serving of the image, which made his the problem of doing something after Response.End had been called.

I've never considered using Response.End() to control program flow.

However Response.End() can be useful for example when serving files to a user.

You have written the file to the response and you don't want anything else being added to the response as it may corrupt your file.

I've used Response.End() in both .NET and Classic ASP for forcefully ending things before. For instance, I use it when there is a certian amount of login attempts. Or when a secure page is being accesed from an unauthenticated login (rough example):

    if (userName == "")
    {
        Response.Redirect("......");
        Response.End();
    }
    else
    {
      .....

When serving files to a user I'd use a Flush, the End can cause issues.

I've only used Response.End() as a testing/debugging mechanism

<snip>
Response.Write("myVariable: " + myVariable.ToString());
Response.End();
<snip>

Judging from what you have posted in terms of research, I would say it would be a bad design if it required Response.End

On classic asp, I had a TTFB (Time To First Byte) of at 3 to 10 seconds on some ajax calls, much larger than the TTFB on regular pages with many more SQL calls.

The ajax returned was a segment of HTML to be injected into the page.

The TTFB was several seconds longer than the render time.

If I added a response.end after the render, the TTFB was greatly reduced.

I could get the same effect by emitting a "</body></html>", but this probably doesn't work when outputting json or xml; here response.end is needed.

Related