5

Using the blog posted here and a topic here on SO i've created a controller which should handle all my error pages.

In my Global.asax.cs I've got the following piece of code:

protected void Application_Error()
        {
            var exception = Server.GetLastError();
            var httpException = exception as HttpException;
            var routeData = new RouteData();

            Response.Clear();
            Server.ClearError();

            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = "General";
            routeData.Values["exception"] = exception;
            Response.StatusCode = 500;

            if (httpException != null)
            {
                Response.StatusCode = httpException.GetHttpCode();
                switch (Response.StatusCode)
                {
                    case 403:
                        routeData.Values["action"] = "Http403";
                        break;
                    case 404:
                        routeData.Values["action"] = "Http404";
                        break;
                }
            }

            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;
            IController errorsController = new ErrorController();
            HttpContextWrapper wrapper = new HttpContextWrapper(Context);
            var rc = new RequestContext(wrapper, routeData);
            errorsController.Execute(rc);
        }

My ErrorController looks like this:

public class ErrorController : BaseController
    {
        /// <summary>
        /// Returns a default view for not having access.
        /// </summary>
        public ActionResult Unauthorized()
        {
            BaseModel viewModel = new BaseModel
                                      {
                                          LoginModel = new LogonModel(),
                                          ProfessionsTopX = GetTopXProfessions()
                                      };
            return View(viewModel);
        }

        public ActionResult General(Exception exception)
        {
            return View("Exception", exception);
        }

        public ActionResult Http404()
        {
            //This line works
            //return Content("Not found", "text/plain");

            //This line presents a blank page
            return View("404","_Layout");
        }

        public ActionResult Http403()
        {
            return View("403", "_Layout");
        }

    }

And my Razor View only contains the piece of html below;

@{
    ViewBag.Title = "404";
}

<h2>404</h2>

This is a 404 page!

When I use the Return Content i'm getting a plain textoutput telling me i'm looking at a 404-page. However, I want the 404 page to fit the rest of my design, so I want to use my own Views. However as soon as I use Return View I'm getting a blank page. I expect to be missing something very obvious, but I don't see it.

Community
  • 1
  • 1
Rob
  • 6,731
  • 12
  • 52
  • 90

2 Answers2

4

I was having the same problem, and finally found the solution that worked for me. The breakthrough came when I placed a breakpoint on the errorsController.Execute(rc); line, and used 'step into' until I came across this exception:

The view 'Detail' or its master was not found or no view engine supports the 
searched locations. The following locations were searched:
~/Views/Errors/Detail.aspx
~/Views/Errors/Detail.ascx
~/Views/Shared/Detail.aspx
~/Views/Shared/Detail.ascx
~/Views/Errors/Detail.cshtml
~/Views/Errors/Detail.vbhtml
~/Views/Shared/Detail.cshtml
~/Views/Shared/Detail.vbhtml

The exception was being swallowed, I assume because it was happening inside the Application_Error method and because I had set Response.TrySkipIisCustomErrors = true.

After seeing this error, I quickly realized my problem was simply one of mismatched names: My controller is actually named ErrorController with no 's', not ErrorsController. The problem for me was that I had set routeData.Values["controller"] = "Errors";, which is wrong. Switching it to routeData.Values["controller"] = "Error"; fixed the problem.

Note that you won't catch the error right away, because you directly instantiate the controller, and it won't compile if you have that part spelled wrong. But inside the controller, calling View() will look for the view using the RouteData instance we constructed and passed to the RequestContext object. So if the controller name is spelled wrong there, MVC doesn't know where to look for the view, and since IIS custom errors are skipped, it fails silently.

Long story short: Check your controller and view names. I assume something similar would happen if you have the controller name correct, but the file name of the view doesn't match.

Katie Kilian
  • 6,815
  • 5
  • 41
  • 64
  • No haven't found a solution, thanks for your response! Seems very logical. Will try this out as soon as possible and get back to you about it! – Rob Sep 28 '12 at 09:12
  • How stupid! I changed the name from Errors into Error and then was able to debug trhough everything. First noticed I still was getting a white page, but after stepping into/through everything I saw an exception coming by which was understandable. Solved it and everything works. – Rob Oct 22 '12 at 19:53
-1

Please check it out this. It is a best way to implement exception handling in mvc.

I have implemented same exception handling but I am facing some issue but still you can refer this.

Community
  • 1
  • 1
alok_dida
  • 1,723
  • 2
  • 17
  • 36
  • Tried it last night, but unfortunately didn't resolve the issue (yet) Other suggestions are welcome! – Rob Jul 26 '12 at 09:00