Skip to main content

Command Palette

Search for a command to run...

Custom error pages for HTTP status codes in ASP.NET MVC

Published
3 min read
Custom error pages for HTTP status codes in ASP.NET MVC
R

I am a recent graduate at the beginning of my software development career. I enjoy documenting my learnings through my blogs

Background

I encountered a problem with my custom error pages when completing a college project. I had 2 HTTP errors which I wanted to use a custom error page for, “404 - Not Found” and “401 - Unauthorized”. To create these custom errors, I first created an “Error” controller and then made an ActionResult method for each error, within this controller and created views for the errors from these methods. The 404 error worked, whereby if an ID was not used in the URL or did not exist, a custom 404 error page was displayed to the user. However, the 401 error I intended to use when a user tried to access certain links/pages when they were not logged in was throwing a runtime error instead of my custom error page.

Creating a custom Error page in MVC

Creating a custom error page is relatively simple. Do note that there is already an Error.cshtml view available in the /Shared/Views folder with the default ASP.NET MVC template.

  1. Create a Controller for the custom error(s) you want to use, I named my controller ErrorController.

  2. Inside this controller you will need a method that returns ActionResult for each error.

     public class ErrorController : Controller
     {
         // GET: Error
         public ActionResult NotFound()
         {
             Response.StatusCode = 404;
             return View();
         }
    
         // GET: Error
         public ActionResult BadRequest()
         {
             Response.StatusCode = 400;
             return View();
         }
     }
    
  3. The next step is creating the relevant views for each error. You can do this by right-clicking on the method name, ie. NotFound and selecting the “Add View” option.

  4. Update the information in this view to whatever you want your error page to tell the user.

  5. Next, open the Web.config file for your MVC application, make sure to choose the correct file as there is a Web.config file in the Views folder (you do not want this file).

  6. In the Web.config file find the <system.web> attribute. Within this attribute add a <customErrors> attribute with mode=”On” . See below for an example…

     <customErrors mode="On">
         <error statusCode="400" redirect="/Error/BadRequest"/>
         <error statusCode="404" redirect="/Error/NotFound"/>
     </customErrors>
    
  7. Open the Global.asax file for your MVC application and in this add the HandleErrorAttibute. The last line in the example is what you will need to add, your code should look something like this.

     protected void Application_Start()
     {
         AreaRegistration.RegisterAllAreas();
         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
         RouteConfig.RegisterRoutes(RouteTable.Routes);
         BundleConfig.RegisterBundles(BundleTable.Bundles);
    
             GlobalFilters.Filters.Add(new HandleErrorAttribute());
     }
    
  8. Lastly, update your exceptions in the relevant controllers. Your exception will look similar to this depending on your error code.

     throw new HttpException(404, "Not Found");
    

Solution

Because my 401 error code would not work for my intended purpose I instead used the [Authorize] attribute on certain actions within my relevant controller, see Simple Authorization for more information on the [Authorize] attribute. For example, I used the [Authorize] attribute to redirect a link to the login page if a user was not logged in. The redirect here is simply a side-effect of the user not being signed in when trying to access a route (Controller action) that is decorated with an [Authorize] attribute. In doing this I did not have to redirect to an error page when a User was not logged in and the [Authorize] attribute was used in its simplest form.

[Authorize]
public ActionResult AddToFavourites(int id)
{
}

Conclusion

In conclusion, my error for code 401 not working was a good thing. This helped me search for alternative solutions to a problem, which led me to the [Authorize] attribute, which turned out to be a better fit for what I wanted.