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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With