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

### 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](http://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.
    
    ```csharp
    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…
    
    ```csharp
    <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.
    
    ```csharp
    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.
    
    ```csharp
    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](https://jakeydocs.readthedocs.io/en/latest/security/authorization/simple.html#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.

```csharp
[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.
