Reputation: 277
I have a MVC4 ASP.NET application and want to build a custom error page to handle any error that can occur, so nobody will face a cryptic error message, only a "Oops, this shouldnt have happened" Page, with the navigation bar on top.
However, in order to help locate the error, i want to add a field to the error page that displays the error that occured.
My Web.config contains:
<customErrors mode="On" defaultRedirect="~/Error">
</customErrors>
The errorpage looks like this:
@{
ViewBag.Title = "Error Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Uups, an error occured</h2>
<p>This should not have happened. Enjoy this error page instead.</p>
<pre>
@ViewBag.ErrorMessage
</pre>
And the error controller is like this:
public class ErrorController : Controller
{
//
// GET: /Views/Error/
public ActionResult Index()
{
var error = Server.GetLastError();
ViewBag.ErrorMessage = error == null ? "" : error.Message;
return View();
}
}
When i enter an invalid path (404 error occurs), the error variable in the error controller is "null", so no error is shown, but the error page appears. What am i doing wrong?
Upvotes: 1
Views: 1535
Reputation: 1
<customErrors mode="On" defaultRedirect="~/Error/Error.html" redirectMode="ResponseRewrite">
<error redirect="~/Error/404.aspx" statusCode="404" />
<error redirect="~/Error/403.aspx" statusCode="403" />
<error redirect="~/Error/500.html" statusCode="500" />
</customErrors>
Create page 404.aspx in root directory "Error"
<%
Server.ClearError();
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
<div>
<h2>404 Not Found</h2>
</div>
Upvotes: 0
Reputation: 1058
I would suggest you tou implement BaseController
which inherits from Controller
and there to override OnException(ExceptionContext filterContext)
. Then all other controllers will inherit from BaseController
and on Exception
you will redirect to your error page.
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
return;
filterContext.Result = new ViewResult
{
ViewName = "~/Error.cshtml",
ViewData = new ViewDataDictionary {{"Exception", filterContext.Exception.Message}}
};
filterContext.ExceptionHandled = true;
}
Upvotes: 1
Reputation: 239210
The error page is a separate response cycle. As a result, anything you set in something like ViewBag
in the original action goes away. You would need to set the error message in something like TempData
or otherwise log it somewhere that you can retrieve from on the error page. However, with either method, be aware that you cannot generate an exception on your error page. Otherwise, you'll send the user on an endless redirect cycle. As a result, it's generally better to keep the error page simple to avoid causing any additional exceptions.
Also, bear in mind that the message you'd be presenting here will still likely be cryptic to the user since they generally won't be developers themselves. And, even if they did understand it, they would still be powerless to do anything about it. Additionally, you're likely to pass information about your server in the error message that you wouldn't want the general public to know about.
The best course of action is always to catch exceptions and recover from them. If the user made a bad request, for example, instead of returning a 400, return the view with a message telling the user what they did wrong and how to recover. If it's an error that you truly can't recover from, then, simply apologize to the user and log the error so that your development team is notified to fix it. There's really no point in telling the user exactly what went wrong in this scenario, because, again, they'll be powerless to correct it on their own.
EDIT
Since your question specifically mentions a 404, the best bet there is to simply create a specific 404 error page. All you could reasonably do from this error is tell the user the page was not found, anyways, and your 404 could then provide some helpful links or a sitemap to help the user recover. Trying to have just one error page than handles any response increases the complexity which also increases the likelihood of triggering an exception from the error page itself (again, huge no-no).
Upvotes: 1