Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpContext throws HttpException

Tags:

I have written a custom http handler. I have done this by writing a class which implements the IHttphandler.

Inside that class I have code like this,

context.Response.Clear();
context.Response.ClearHeaders();
context.Response.AddHeader("Content-Disposition", "attachment;filename=" + attachmentFileName);
context.Response.AddHeader("Content-Length", new FileInfo(downloadFile).Length.ToString());
context.Response.ContentType = GetMimeType(attachmentFileName);
context.Response.TransmitFile(downloadFile);
context.Response.Flush();
context.Response.Close();

Occasionally I receive an error like this,

Exception HttpException The remote host closed the connection The error code is 0x800703E3

Or this,

Exception HttpException The remote host closed the connection The error code is 0x80070040

In both cases the stack trace is this,

at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)
at System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()
at System.Web.HttpResponse.Flush(Boolean finalFlush)
at System.Web.HttpResponse.Flush()

This occurs in production, and if I look back over the last few days errors have occurred 23 times, and in total the above code has been called 497 times.

I suspect this failure relates to the user clicking the link to initiate the above code more than once (which will give them multiple download dialogs) then they cancel some of them. Having said that if it was something like that I would have expected the connection to close gracefully at both ends.

How can I prove the exact cause of this error? I have tried to enable .NET tracing like this Why don't trace listeners log custom handler traffic? but couldn't get it to work.

What I found though is that I have enabled IIS tracing to log failed requests. The failure occurred again, and NOTHING was in that log.

Any other tracing I can enable for instance?

The next thing I tried was this,

if (context.Response.IsClientConnected)
{
    context.Response.Flush();
    context.Response.Close();
}
else
{
    LogMessage("Client has disconnected before flush was called", Severity.Information);
}

But that didn't make any difference. The reason though I guess is that the client disconnected while the download was taking place, not before flush was called.

like image 296
peter Avatar asked Apr 03 '11 22:04

peter


People also ask

What is HttpContext HTTP request and Httpresponse?

HttpRequest is a subset of HttpContext . In other words, the HttpContext includes the response, the request, and various other data that's not relevant to a specific request or response; such as the web application, cached data, server settings and variables, session state, the authenticated user, etc.

When should I use HttpContext items?

Similarly, you use HTTPContext Items collection when you are sharing the same information across the different instance based on the user request and that request could be changed for a different request.

Is HttpContext current items thread safe?

The HttpContext is NOT thread safe, accessing it from multiple threads can result in exceptions, data corruption and generally unpredictable results.

How does HttpContext current work?

From ASP.NET 4.5 and after, Current HttpContext is passed through CallContext instead of [ThreadStatic] , so context remains available through out async calls in single logical context instead of current thread as each async call may end up on different threads.


2 Answers

Take out both the Flush() and Close() call. You really don't need them. Once your handler is done, it'll exit, and ASP.NET will handle closing the request.

Besides, Flush() should be used when you're streaming content to the client (adding parts to the response stream in blocks). You don't need to use it with TransmitFile().

like image 127
Samuel Neff Avatar answered Oct 20 '22 08:10

Samuel Neff


I was into similar issues, got this article which explains that Response.End() should be avoid ed and instead suggests to use CompleteRequest() method. MSDN documentation has also been updated with this information. I hope this helps someone.

http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx

like image 44
DotNetUser Avatar answered Oct 20 '22 07:10

DotNetUser