Jump to content

HttpUnhandledException on File Upload


jesh

Recommended Posts

I have a file upload control on one of my pages which works flawlessly - as long as the user doesn't attempt to upload a file larger than .NET's default maxRequestLength of 4096 KB.I don't want to change the maxRequestLength (if anything, I might make it smaller), but I want to handle this error in a graceful way rather than spitting out the awful "Cannot connect to server" error.I understand that I can add some global error handling in with the Application_Error event handler in the Global class, but I was wondering if anyone here has experienced this and used some other means of handling this error?I can do:

protected void Application_Error(object sender, EventArgs e){	Exception exception = Server.GetLastError();	HttpUnhandledException uhex = (exception as HttpUnhandledException)	if(uhex != null)	{		// do my error processing here...	}}

But does anyone know if there are any page-level methods I could employ?

Link to comment
Share on other sites

The problem is that IIS rejects the request before the OnLoad event on the page gets any chance of running. This means that I can't add any error handling in the page.I've tried both the Application_Load and Page_Load event handlers, and I can get at the Exception, but IIS won't allow me to use a Server.Transfer() or a Response.Redirect(). And no matter what I put in the Web.config for customErrors, it's all ignored.Doesn't work:

protected void Page_Error(object sender, EventArgs e){	Exception exception = Server.GetLastError();	if (exception is HttpException)	{		Server.ClearError();		Response.Redirect("Error.aspx");		// Server.Transfer("Error.aspx");		// Code executes up to this point, but the page still loads the		// "The connection was reset" in Firefox and "Cannot find server or DNS Error"		// in IE.	}}

Neither does this:

protected void Application_Error(object sender, EventArgs e){	Exception exception = Server.GetLastError();	if (exception is HttpUnhandledException)	{		if (exception is HttpException)		{			Server.ClearError();			Response.Redirect("Error.aspx");		}	}}

Neither does this in the Web.config:

<customErrors mode="On" defaultRedirect="Error.aspx">	<error statusCode="403" redirect="Error.aspx">	<error statusCode="404" redirect="Error.aspx">	<error statusCode="500" redirect="Error.aspx"></customErrors>

And I can't use the FileInfo class because 1) the file resides on the client computer and 2) the request never gets to complete.I'm starting to investigate whether I can hijack the request in the Application_BeforeRequest event handler and stop it before the exception is thrown.

Link to comment
Share on other sites

I fail to understand why you can't place the upload code in a try catch and hadle errors from there???
I can place the upload code in a try/catch block. The problem that I'm encountering, however, is that IIS is flat out rejecting the request before it even gets through to the page. So the upload code never executes - the request isn't making it to the page.The person submits the form, it gets posted back to my page, and then, before the OnInit event fires, IIS rejects the request because of the maxRequestLength.I'm starting to think this is an impossibility.
Link to comment
Share on other sites

oh ok, sorry, I was sniffing glue :).Hmm...in that case no matter what .Net code you write you cannot catch this error because it is not a .Net error. It is a IIS error. That being said, I can think of only 1 option.-Set IIS to accept really large files and manage it with your code.

Link to comment
Share on other sites

Yeah, I'm starting to see that as my only option. I've found other articles on the Internet that say that I should be able to do something like this in the Page_Error event handler:

protected void Page_Error(object sender, EventArgs e){	string message = Server.GetLastError().Message;	Server.ClearError();	Response.Redirect("~/Error.aspx?error=" + message);}

I've placed breakpoints on each step there and the code seems to execute properly (i.e. Server.GetLastError() returns null after calling Server.ClearError()) but the page never redirects. Furthermore, this event fires twice when I upload a file which is too large (and the Application_BeginRequest event fires twice as well). Any idea why I'd be getting two requests?

Link to comment
Share on other sites

I'm not sure. Perhaps IIS drops the request whne the file is too big and then attempts to pick it back up???
Well, I just ran a test. My maxRequestLength is set to 4096 (4MB). In my Global.asax file, I have the following:
protected void Application_BeginRequest(object sender, EventArgs e){	Server.Transfer("Error.aspx");}

This, as would be expected, sends all requests to "Error.aspx". Not very usefull, to be sure, but it does prove that you can transfer the request to the Error page from within this event handler.However, when I change the code to:

protected void Application_BeginRequest(object sender, EventArgs e){	if(Request.ContentLength > 0)	{		Server.Transfer("Error.aspx");	}}

It breaks. Simply visiting any page transfers the user to "Error.aspx" as before, but as soon as you post a request with a content-length > 0 (i.e. upload a file of 10KB, 100KB, 1MB, etc), the Application_BeginRequest event handler fires twice and I get that "Connection was reset" error in Firefox. Any ideas? Have you seen anything like this before? ASP.NET 2.0, IIS 5.1

Link to comment
Share on other sites

OMG, I found a solution here!This is what I had to add to my BeginRequest event handler. Now I just need to understand what's going on! heh. I'll look into it later, I suppose.Here's the code:

protected void Application_BeginRequest(Object sender, EventArgs e){    int maxRequestLength = 1048576; // 1MB    if (Request.ContentLength > maxRequestLength)    {        HttpApplication app = sender as HttpApplication;        HttpContext context = app.Context;        HttpWorkerRequest wr = (HttpWorkerRequest)(context.GetType().GetProperty("WorkerRequest", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(context, null));        byte[] buffer;        if (wr.HasEntityBody())        {            int contentlen = Convert.ToInt32(wr.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));            buffer = wr.GetPreloadedEntityBody();            int received = buffer.Length;            int totalrecv = received;            if (!wr.IsEntireEntityBodyIsPreloaded())            {                buffer = new byte[65535];                while (contentlen - totalrecv >= received)                {                    received = wr.ReadEntityBody(buffer, buffer.Length);                    totalrecv += received;                }                received = wr.ReadEntityBody(buffer, contentlen - totalrecv);            }        }        context.Response.Redirect("~/Error.aspx");    }}

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...