Last December someone used the feedback link on the HttpResponse.Close method in MSDN to send the following comment: “Where is any context on use and what is actually occurring?”
I maintain the HttpResponse class documentation, so this comment got routed to me. I did not assign it a high priority because it was not reporting an error and the HttpResponse.Close documentation was not getting a lot of traffic. But I put it in my to-do list, and eventually I found time to look into it further.
The comment was an understandable response to a minimal amount of documentation: all we had on HttpResponse.Close was a brief summary (“Closes the socket connection to a client.”) and a one-line code example with an introduction that repeated the summary.
I did not know any more about the HttpResponse.Close method at this point than the customer who was frustrated by the brevity of our documentation. So I started with some Bing queries to see what information about this might already be available on the web. (Of course I work right here in the same building with the developers who created and maintain the HttpResponse class, and I could have gone straight to the horse’s mouth. But it’s generally better not to bother busy people with questions that you can find out quickly and easily in other ways.)
This one was not quick and easy. What I found was a lot of confusion. Many people were trying to use HttpResponse.Close but they didn’t know what it was for, and they were having various problems with it. They were asking questions and not getting answers, or they were getting incomplete or inconsistent answers. Finally I found a forum post where a Microsoft person gave an answer that got me closer to what I was looking for. Here is how he answered a question about why using HttpResponse.Close caused some data sent to the client to be lost:
Response.Close sends a reset packet to the client and using it in anything other than error condition will lead to all sorts of problems – e.g., if you are talking to a client with enough latency, the reset packet can cause any other response data buffered on the server, client or somewhere in between to be dropped.
In this particular case, compression involves looking for common patterns within the response and some amount of response has to be buffered by the compression code to increase the chance of finding longer repeating patterns – this part that is buffered cannot be sent to the client once you do Response.Close().
In short, do not use Response.Close().
I asked the post’s author (Anil Ruia) when you might actually want to use HttpResponse.Close. He wrote back that “… it should really only be used under error conditions to abort the response/connection.” He cc’d another expert on the subject, Thomas Marquardt, who stated unequivocally:
It’s definitely in the “don’t use this API ever” category … Response.End does in fact abort the current thread, so I wouldn’t use the term “abort” when talking about Response.Close, for fear of confusion. Response.Close calls HttpWorkerRequest.CloseConnection, which is described on MSDN as “Terminates the connection with the client.” The only thing I would add to the description of Response.Close on MSDN is that you shouldn’t call it, ever.
This left me in a bit of a quandary, because if I updated the documentation to say “don’t use this ever,” people would wonder why it’s there in the first place. A follow-up email to Thomas elicited a more complete description of not only HttpResponse.Close but also HttpResponse.End:
The End method is also on my “never use” list. The best way to stop the request is to call HttpApplication.CompleteRequest. The End method is only there because we tried to be compatible with classic ASP when 1.0 was released. Classic ASP has a Response.End method that terminates processing of the ASP script. To mimic this behavior, ASP.NET’s End method tries to raise a ThreadAbortException. If this is successful, the calling thread will be aborted (very expensive, not good for performance) and the pipeline will jump ahead to the EndRequest event. The ThreadAbortException, if successful, of course means that the thread unwinds before it can call any more code, so calling End means you won’t be calling any code after that. If the End method is not able to raise a ThreadAbortException, it will instead flush the response bytes to the client, but it does this synchronously which is really bad for performance, and when the user code after End is done executing, the pipeline jumps ahead to the EndRequest notification. Writing bytes to the client is a very expensive operation, especially if the client is halfway around the world and using a 56k modem, so it is best to send the bytes asynchronously, which is what we do when the request ends the normal way. Flushing synchronously is really bad. So to summarize, you shouldn’t use End, but using CompleteRequest is perfectly fine. The documentation for End should state that CompleteRequest is a better way to skip ahead to the EndRequest notification and complete the request.
The Close method isn’t for debugging scenarios. Close terminates the connection with the client in an abrupt manner, and is not intended for normal HTTP request processing. This is the kind of thing you might do if your server was being attacked by a malicious HTTP client. It’s highly unlikely that you would have a good reason to call this method. You might consider calling CompleteRequest instead if you want to jump ahead to EndRequest and send a response to the client.
A review of the existing MSDN documentation for HttpResponse.End revealed that it too was in need of revision. So I updated the MSDN documentation for both HttpResponse.End and HttpResponse.Close to indicate briefly what they actually do and that HttpApplication.CompleteRequest is a better way to end a request. (Updates do not immediately go through to the public MSDN site; I would expect it to appear there in a month or so.)
I am providing this blog post as an example that shows how customer feedback comments, even simple requests for more information, can make a difference in improving MSDN documentation. It might take 6 months or more (as in this case) for you to see a change in MSDN due to our workload and other priorities, but every feedback comment gets personal attention and is taken seriously.
— Tom Dykstra
ASP.NET User Education
This posting is provided “AS IS” with no warranties, and confers no rights.
— Tom Dykstra