HttpResponse.End vs HttpResponse.Close vs HttpResponse.SuppressContent

Viewed 24582

Within an ASPX page, I want to end the response at specific points (not due to an error condition), depending on code path, so that nothing else is sent back down the stream. So naturally used:

Response.End();

This results in a ThreadAbortException, which is by design.

The following seems to work but does not look like the correct approach as per this SO question:

Response.Flush();
Response.Close();

So, how about this?

Response.Flush();
Response.SuppressContent = true

and then just let the page complete normally.

I could just handle and swallow the ThreadAbortException, but I just want to find out if there is anything wrong/gotchas with the SuppressContent approach?

Edit: To give a bit more of an example. Say I have a ASPX page whereby I may change the content-type to one of a number of possibilities. Depending on the content-type and scenario, at a given point in the code I want to prevent any more content from being sent to the client. Assume after SuppressContent has been set set to true, that there is no issue with any further server-side code running. I just don't want anything else to be sent to the client.

Edit 2: MyPage.aspx - has a master page which may include standard content, headers, footers etc etc. This page can just render as a normal page. It also can just write out an (e.g.) XML document to be downloaded. If writing out an XML document (determined on page load), it will clear the ouput, set the content-type to XML, write all the XML out and then if left normally, you end up with the rest of the ASPX page rendering being tacked on to the end - that is obviously not required/breaks the XML.

Edit 3: For now I'm using the SuppressContent approach. To try and draw this question to a close, I'm raising a bounty and will put the question another way: When should you use SuppressContent? Why would you use it instead of Response.End?


Please see the answer I provided below for the solution I actually ended up with as I eventually found a way to avoid the ThreadAbortException when using Response.End. I had already excepted an answer by this point.


6 Answers

I eventually found a simple solution to using Response.End() without getting a ThreadAbortException.

Response.Flush();
Response.End();

From my original question, I'd always been trying JUST a Response.End() after sending some content to the response stream.

It seems that if there is unflushed content when you do Response.End(), you get the ThreadAbortException. By doing the Flush immediately before the End, a ThreadAbortException does not actually get thrown.

Seems to be working great - no ThreadAbortException is being thrown now when I use Response.End

update - warning: there is a better method, don't use this, see Ethan's answer instead!

I wouldn't say there is a valid reason to avoid the Response.End. Wanting to avoid the cost of the ThreadAbortException, by letting the page request cycle go on and have it do extra work that isn't necessary doesn't seem right.

ThreadAbortException is a special type of exception meant to stop a thread from execution (its re-thrown automatically even if caught). That said, there are some scenarios where it could do harm (see community content added at the end of ThreadAbortException).

Unless you are in one of those scenarios you should stick to Response.End. Note that some usages around, do a SuppressContent & Response.End, I guess in cases that you want to avoid some stuff that would come from the internal Response.Flush.

This is a very common question. And it is almost always a mistake to call anything except Response.End(). Here is the description of End() from MSDN:

Sends all currently buffered output to the client, stops execution of the page, and raises the EndRequest event.

This seems to be exactly what you want to do. And you will notice in the last part that it raises the EndRequest event. This means that after End() is called, all data is flushed to the client that has been written before the End(), the socket is closed, and resources are freed, and your program stops processing the request right away.

What if, after calling Response.SuppressContent = true your page goes on to make changes to a record in the database?

As far as I can understand the code when reflecting HttpResponse using the Flush/SuppressContent approach will make you vulnerable to code trying to do header changes after flush. Changing a header after flush will give a HttpException.

I would use Response.End() to be absolutely sure that nothing else could interfere with the response.

If you want to continue execution but also short circuit the http pipeline consider using Response.Flush() and HttpContext.Current.ApplicationInstance.CompleteRequest() like Response.End() does when the context is not in a cancellable period.

Related