7
votes

I am fairly new to ASP.NET and MVC in general; I have been migrating an ASP.NET MVC app to ASP.NET MVC Core. In the former framework I was able to handle an HttpException for the following infamous error:

HTTP Error 404.13 - Not Found

The request filtering module is configured to deny a request that exceeds the request content length.

I am aware I can increase the maximum upload allowed length, which currently is 30MB by default, but my objective is to present the user with a friendly error page explaining what just happened, not increase the allowed limit.

On ASP.NET I did this with the following code on my Global.asax :

private void Application_Error(object sender, EventArgs e)
{
    var ex = Server.GetLastError();
    var httpException = ex as HttpException ?? ex.InnerException as HttpException;
    if (httpException == null) return;

    if (httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge)
    {
        //handle the error
        Response.Redirect("~/Error/UploadTooLarge"); //Redirect to my custom error page

    }
}

I can't seem to find an alternative for this in Asp.Net Core after several hours of research. I believe I will need to plug in some Middleware in my Startup.cs Configure method to achieve a custom error page to handle the HttpException and redirect it but I am truly lost on this matter.

I have managed to successfully use the following middleware for custom error pages for http errors such as 404 - Not Found or 403 - Forbiden by using the following on my configure method :

app.UseStatusCodePagesWithReExecute("/Error/StatusCode{0}");

Alongside a controller:

public class ErrorController : Controller
{
    public IActionResult StatusCode404()
    {
        return View(viewName: "CustomNotFound"); 
    }

    public IActionResult StatusCode403()
    {
        return View("CustomForbiden");
    }
}

And the corresponding views. However, the 404.13 error (upload too large) wont be handled by my current middleware. I believe IIS is presenting the error as it is not handled by the web app.

2

2 Answers

2
votes

You are correct. IIS is nabbing the error before it gets into your pipeline. I would recommend adding the httpErrors module into your web.config and pointing it at a page on the site.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="13" />
    <error statusCode="404"
           subStatusCode="13"
           prefixLanguageFilePath=""
           path="http://yourwebsite.com/path/to/page"
           responseMode="Redirect" />
  </httpErrors>
</system.webServer>
3
votes

Old post, but still relevant. My Core 2.2 MVC project, which include large streaming file uploads, needed a graceful handling of a 404.13 (request size too large) result. The usual way of setting up status code handling (graceful views) is in Startup.cs Configure() plus an action method to match:

app.UseStatusCodePagesWithReExecute("/Error/Error", "?statusCode={0}");

and

public IActionResult Error(int? statusCode = null)
{
    if (statusCode.HasValue)
    {
        Log.Error($"Error statusCode: {statusCode}");
        if (statusCode == 403)
        {
            return View(nameof(AccessDenied));
        }
        if (statusCode == 404)
        {
            return View(nameof(PageNotFound));
        }
    }

    return View(new ErrorViewModel 
        {
            RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier 
        });
}

But because a 404.13 error is handled by IIS, not in the MVC pipeline, the code above did not allow establishing a graceful 'upload too large' error view. To do that, I had to hold my nose and add the following web.config to my Core 2.2 project. Note that removing the 404.13 also removed 404, so the ErrorController() code no longer handled 404s, hence the two custom error handlers below. Hope this helps someone!

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <!-- This will handle requests up to 201Mb -->
        <requestLimits maxAllowedContentLength="210763776" />
      </requestFiltering>
    </security>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" subStatusCode="13" />
      <remove statusCode="404" />
      <error statusCode="404"
             subStatusCode="13"
             prefixLanguageFilePath=""
             path="/Error/UploadTooLarge"
             responseMode="Redirect" />
      <error statusCode="404"
             prefixLanguageFilePath=""
             path="/Error/PageNotFound"
             responseMode="Redirect" />
    </httpErrors>
  </system.webServer>
</configuration>