I’m struggling to understand how to correctly handle errors in ASP.NET MVC4. As an example, I’ve created a new MVC4 project using the “Internet Application” template and updated my home controller to test out some error cases:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Hello";
return View();
}
public ActionResult About()
{
throw new HttpException(401, "Not Authorized");
}
public ActionResult Contact()
{
throw new Exception("Oh no, some error occurred...");
}
}
I have enabled customErrors in my web.config file:
<customErrors mode="On"></customErrors>
When I run the app and click “Contact”, I see the ~/Views/Shared/Error.cshtml view as expected, since I have the HandleErrorAttribute registered as a global filter.
However, when I click “About”, I get the standard ASP.NET yellow error page that says “Runtime Error”. Why are these two exceptions being handled differently and how can I get instances of HttpException to get caught using the HandleError attribute?
CustomErrors config
Ideally, I’d like custom error pages for the following:
- A custom 404 (not found) page that’s nice and user friendly
- A custom 401 (not authorised) page that informs the user that they do not have access (e.g. thrown after checking permissions for a particular item in the model)
- A generic error page that is used in all other cases (in place of the standard yellow ASP.NET page).
I’ve created a new “Error” controller with views for each of the scenarios above. I have then updated customErrors in web.config like so:
<customErrors mode="On" defaultRedirect="~/Error/Trouble">
<error statusCode="404" redirect="~/Error/NotFound"></error>
<error statusCode="401" redirect="~/Error/NotAuthorized"></error>
</customErrors>
The 404 page works fine, but I don’t get the 401 page at all. Instead, I get the ~/Error/Trouble view (the one specified as the defaultRedirect) when I try to access the About action on the Home controller.
Why is my custom 401 redirect page not working?
ASP.NET uses 401’s internally to redirect users to the login page. Wherever you were planning to throw a 401 unauthorized, instead throw a 403 forbidden.