2

I've done a bit of research into HttpHandlers and HttpModules and I'm not clear on the best way to implement this to my specifications.

My issue is that the StaticFile handler handles all urls with extensions and will return a default IIS 404 page instead of visiting the NotFound action of my ErrorsController. I want to use MVC to handle all 404s because of the benefits of using .cshtml pages over .html pages along with the fact that I perform logging and of all 404 responses and the pages contain some dynamic content.

I don't want to enable <modules runAllManagedModulesForAllRequests="true"> because of the performance impact it causes and because it seems like the wrong way to do this.

Is it plausible to create an HttpModule and have it check for the existence of the requested file and, if not found, send the request to the managed pipeline and eventually to my ErrorsController to handle the request?

Slight
  • 1,541
  • 3
  • 19
  • 38
  • Not confirmed, but doesn't global_asax `Application_Error` pick up all errors? or do static files bypass this? – freedomn-m Jun 24 '15 at 17:24
  • 1
    No, static files don't reach the managed pipeline. I'm using `Application_EndRequest` which is more robust. What's interesting is that some file extensions do because they are handled by a handler other than `StaticFile`. Extensions like .cshtml, .axd, .rem, .aspq, .vbhtml, etc all run through the managed pipeline with a proper 404 message that I can catch. – Slight Jun 24 '15 at 17:54
  • IIS (Custom Error Page) lets you respond with a 302 redirect which you can set per status code. So your 404 error can respond with a url to your application. I have never tried this though. – Jasen Jun 24 '15 at 17:58
  • @Jasen The issue there is I don't think I can get the original request path or any request parameters which I want to log. I also try to log the sub status code which iis will populate if it rejected the request because, for example, it contained doubly escaped characters. – Slight Jun 24 '15 at 18:17
  • I'm not sure if I'm understanding fully so forgive me but could you use `httperrors` (or `customerrors` if you have older IIS) in the web.config, point the particular code to a method in an `Error` controller, pull whatever you want from `Request` for logs and deliver the desired status code and cshtml view? See here for more detail (if relevant): http://stackoverflow.com/questions/28989026/how-do-i-catch-the-http-status-code-of-server-errors-into-a-generic-custom-error/28991628#28991628 – scgough Jun 24 '15 at 20:14
  • @scgough Yes, while I haven't had the time to test such a method yet, I think that is my best option. The custom errors module is a native module and should allow me to trigger a 404 for anything if done right. http://stackoverflow.com/questions/717628/asp-net-mvc-404-error-handling the second anwser outlines all the ups and downs of doing so. His proposed solution is the one I'm currently using and it doesn't handle file extensions related 404s. – Slight Jun 25 '15 at 13:30

1 Answers1

0

My solution here handles all 404s from unauthenticated users, this includes all urls with file extensions. The nice thing about this solution is existingResponse='Auto' determines if a 404 is already handled by the ErrorController and if so it will skip this step but if not, use the provided custom error page.

You will have to skip IIS Custom errors with Response.TrySkipIisCustomErrors = true;.

You might have to set the status code again in the method using Response.StatusCode = (int)HttpStatusCode.NotFound;

In your ErrorController

 [HttpGet]
        public ActionResult 404()
        {
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            Response.TrySkipIisCustomErrors = true;
            return View("Index", new ErrorModel
            {
//Fill in properties values you have in your ErrorModel.
         
            });
        }

In your webconfig.

  <httpErrors errorMode="Custom" existingResponse="Auto">
      <remove statusCode="404" />
      <error statusCode="404" path="/Error/404" responseMode="ExecuteURL" />
    </httpErrors>

Jayowl
  • 280
  • 3
  • 11