Asp.Net Mvc Custom Error Pages Complete Guide

 Last Update:2025-06-23T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    8 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of ASP.NET MVC Custom Error Pages

ASP.NET MVC Custom Error Pages: A Comprehensive Guide

Introduction to Error Pages in ASP.NET MVC

By default, ASP.NET MVC displays generic error messages that are not particularly user-friendly nor visually appealing. Custom error pages allow you to define what users see when errors such as 404 Not Found, 500 Internal Server Error, or other types occur. This approach improves usability and maintains a consistent brand presence even in critical moments.

Understanding Web.config Settings

The primary configuration settings for error handling in ASP.NET MVC reside within the Web.config file. Here are the essential elements:

  1. customErrors: Manages HTTP error responses. The mode attribute (On, Off, RemoteOnly) controls when custom errors are shown.

    <system.web>
        <customErrors mode="On" defaultRedirect="~/Error/GeneralError">
            <error statusCode="404" redirect="~/Error/NotFound"/>
            <error statusCode="500" redirect="~/Error/InternalError"/>
        </customErrors>
    </system.web>
    
  2. httpErrors: Provides more robust control over HTTP error responses than customErrors.

    <system.webServer>
        <httpErrors existingResponse="Replace" errorMode="Custom">
            <remove statusCode="404"/>
            <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL"/>
            <remove statusCode="500"/>
            <error statusCode="500" path="/Error/InternalError" responseMode="ExecuteURL"/>
        </httpErrors>
    </system.webServer>
    
  3. handleErrorAttribute: Used as a filter to specify which controller actions return a specific error view. You can apply it globally through action filters.

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
    }
    
  4. Global Exception Handling: Implementing global exception handling allows you to capture unhandled exceptions throughout your application and redirect them to appropriate error views. This is typically done by overriding Application_Error in Global.asax.

    protected void Application_Error(object sender, EventArgs e)
    {
        var httpContext = ((MvcApplication)sender).Context;
        var exception = Server.GetLastError();
        var routeData = new RouteData();
        var action = "GeneralError";
    
        if (exception.GetType() == typeof(HttpException))
        {
            var httpCode = ((HttpException)exception).GetHttpCode();
    
            switch (httpCode)
            {
                case 404:
                    action = "NotFound";
                    break;
                case 500:
                    action = "InternalError";
                    break;
                // Add additional cases here ...
            }
        }
    
        routeData.Values["controller"] = "Error";
        routeData.Values["action"] = action;
    
        server.ClearError();
        server.Transfer(Request.Url.AbsolutePath + "?aspxerrorpath=" + Request.Url.PathAndQuery, routeData);
    }
    

Creating Error Views

Once you've configured the error redirections, you need to create corresponding error views within your application. Place these views inside the Views/Shared folder or a dedicated Views/Error directory.

GeneralError.cshtml

This view displays a generic error message when an unhandled exception occurs.

@{
    ViewBag.Title = "An Error Occurred";
}

<h2>@ViewBag.Title</h2>
<p>Sorry, something went wrong on our end. We'll look into it.</p>
NotFound.cshtml

This view informs users that the requested page cannot be found.

@{
    ViewBag.Title = "404 Not Found";
}

<h2>@ViewBag.Title</h2>
<p>The page you are looking for does not exist or has been moved.</p>
<a href="@Url.Action("Index", "Home")">Go back to the home page</a>
InternalError.cshtml

Designed for internal server errors, this view should be kept more generic in production environments.

@{
    ViewBag.Title = "500 Internal Server Error";
}

<h2>@ViewBag.Title</h2>
<p>We apologize, but there was an unexpected problem. Our team has been notified.</p>
<a href="@Url.Action("Index", "Home")">Return to the Home Page</a>

Best Practices

  • Security: Avoid showing detailed stack traces to users, especially in production environments. They could provide sensitive information about your application’s architecture.

  • User Experience: Provide a clear and concise message indicating an error occurred and suggestions on how to proceed or contact support.

  • Logging: Use logging frameworks like NLog or log4net to capture exceptions for post-mortem analysis and troubleshooting.

  • Testing: Regularly test various scenarios to ensure that your custom error pages display correctly. Use tools like Postman or Fiddler for testing.

  • Consistency: Maintain a consistent design style across all error views. This strengthens brand recognition and keeps the user experience cohesive across different states and conditions.

Common Issues and Solutions

  1. Error Pages Not Displaying: Ensure that both customErrors and httpErrors are correctly configured and that the mode attribute in customErrors is set to On.

  2. Handling Unhandled Exceptions: Override Application_Error in Global.asax to catch and handle unhandled exceptions effectively.

  3. Development vs Production Modes: In production, set the mode attribute to On. In development, consider setting it to Off or RemoteOnly to see detailed error information for debugging purposes.

  4. Detailed Error Information in Production: To prevent detailed error information from being shown unintentionally, ensure proper setup of the httpErrors element and avoid displaying exception details in custom error views served in production environments.

Conclusion

Implementing custom error pages in ASP.NET MVC not only enhances the user experience but also aids in maintaining the integrity of your application's interface during exceptional situations. By configuring Web.config properly and creating dedicated error views, you can provide meaningful feedback to users while keeping a secure and efficient development process. Always prioritize user experience and security in your error-handling strategy to build reliable and trustworthy web applications.


Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement ASP.NET MVC Custom Error Pages

Step 1: Set Up Your ASP.NET MVC Project

If you haven't already set up your ASP.NET MVC project, you can do so by opening Visual Studio and creating a new project.

  1. Open Visual Studio.
  2. Create a New Project: Go to File > New > Project.
  3. Select Template: Choose ASP.NET Web Application (.NET Framework) under Installed Templates.
  4. Name Your Project and choose a location.
  5. Choose ASP.NET MVC Template: Select MVC from the templates list, and then click Create.

Step 2: Configure Web.config for Custom Errors

You need to configure the Web.config file to tell the application to use custom error pages.

  1. Open the Web.config file located at the root of your project.
  2. Find the <system.web> section.
  3. Add or modify the <customErrors> element within it.

Here is an example configuration:

<system.web>
    <compilation debug="false" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />
    <customErrors mode="On" defaultRedirect="~/Error/Index">
        <error statusCode="404" redirect="~/Error/NotFound" />
        <error statusCode="500" redirect="~/Error/InternalServerError" />
    </customErrors>
</system.web>
  • mode="On": Ensures that custom errors are displayed.
  • defaultRedirect="~/Error/Index": Specifies the default page to display when any error occurs.
  • <error statusCode="404" redirect="~/Error/NotFound"/>: Specifies the page to display when a resource is not found (404 error).
  • <error statusCode="500" redirect="~/Error/InternalServerError"/>: Specifies the page to display when an internal server error occurs (500 error).

Step 3: Create Error Controller

The controller will handle routing to your custom error pages.

  1. Right-click on the Controllers folder and select Add > Controller.
  2. Select the Controller Template: Choose MVC 5 Controller - Empty, name it ErrorController.
  3. Click Add.

Now add actions to handle different error codes.

public class ErrorController : Controller
{
    // GET: Error
    public ActionResult Index()
    {
        ViewBag.Title = "An Error Occurred";
        ViewBag.Message = "An unexpected error occurred. Please try again later.";
        return View();
    }

    // GET: Error/NotFound
    public ActionResult NotFound()
    {
        ViewBag.Title = "Not Found";
        ViewBag.Message = "The requested resource was not found.";
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View("NotFound"); // You could return a different view
    }

    // GET: Error/InternalServerError
    public ActionResult InternalServerError()
    {
        ViewBag.Title = "Internal Server Error";
        ViewBag.Message = "There was an error on the server. Please try again later or contact support.";
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return View("InternalServerError");
    }
}

Step 4: Create Error Views

Now, create views corresponding to the actions you added in the ErrorController.

  1. Right-click on Views folder and select Add > New Folder.
  2. Name the folder Error.
  3. Inside the Error folder, right-click and select Add > View.
  4. For each action (Index, NotFound, InternalServerError), create a corresponding view with the same name and layout.

Example Index.cshtml (Default Error Page)

Create this view inside the Views/Error folder.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Error";
}

<hgroup>
    <h1>@ViewBag.Title.</h1>
    <h2>@ViewBag.Message</h2>
</hgroup>

<p>
    We're sorry, but something went wrong while processing your request.
</p>
<a href="@Url.Action("Index", "Home")">Back to Home</a>

Example NotFound.cshtml (404 Error Page)

Create this view inside the Views/Error folder.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Not Found";
}

<hgroup>
    <h1>@ViewBag.Title.</h1>
    <h2>@ViewBag.Message</h2>
</hgroup>

<p>
    The page you are looking for cannot be found. Please check the URL and try again.
</p>
<a href="@Url.Action("Index", "Home")">Back to Home</a>

Example InternalServerError.cshtml (500 Error Page)

Create this view inside the Views/Error folder.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Internal Server Error";
}

<hgroup>
    <h1>@ViewBag.Title.</h1>
    <h2>@ViewBag.Message</h2>
</hgroup>

<p>
    An unexpected error has occurred on the server. Please try again later or contact support for assistance.
</p>
<a href="@Url.Action("Index", "Home")">Back to Home</a>

Step 5: Test Custom Error Pages

To test your custom error pages, you can do the following:

  • Create a Test 404 Error: Try to navigate to a non-existent route like /NonExistent. You should see your custom 404 error page.

  • Create a Test 500 Error: Modify one of your controllers or models to throw an exception intentionally. Run your application and access that controller/action. You should see your custom 500 error page.

Intentionally Throwing an Exception for Testing

Here’s a simple way to create a 500 error:

public class Homecontroller : Controller
{
    public ActionResult Index()
    {
        throw new Exception("Intentional exception for testing");
        // other code goes here
    }
}

After doing this, navigate to /Home/Index and you should see the 500 error page you created.

Step 6: Handling Global Exceptions (Optional)

For even more robust error handling, you might consider adding a global exception filter. This is useful for catching exceptions that aren't caught by the specific controller actions.

  1. Open App_Start/FilterConfig.cs.
  2. Add a HandleErrorAttribute:
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}
  1. Modify HandleErrorAttribute:

This filter attribute automatically redirects to the specified error view if an exception occurs. You can customize it if needed.

Conclusion

By following these steps, you can create custom error pages in an ASP.NET MVC project. These custom error pages allow you to manage different types of errors gracefully and provide a better user experience.

Top 10 Interview Questions & Answers on ASP.NET MVC Custom Error Pages

Top 10 Questions and Answers on ASP.NET MVC Custom Error Pages

Q1: How do I enable custom error pages in an ASP.NET MVC application?

A1: You can enable custom error pages by configuring the <customErrors> element in your Web.config file, setting the mode to “on” and specifying the path for your error page. Here's an example:

<system.web>
    <customErrors mode="On" defaultRedirect="~/Error/GeneralError">
        <error statusCode="404" redirect="~/Error/NotFound"/>
    </customErrors>
</system.web>

Q2: Can I use custom error pages with ASP.NET MVC 6 (Core)?

A2: In ASP.NET Core MVC, configuring custom error pages is different. You typically handle errors in the middleware pipeline using app.UseExceptionHandler. For example:

if (!env.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
}

You can also specify a custom status code response handler:

app.UseStatusCodePagesWithReExecute("/Home/Error", "?statusCode={0}");

Q3: What is the best way to handle 404 errors specifically in ASP.NET MVC?

A3: To handle 404 errors specifically, configure it as shown in Q1, or you can catch these in the controller using Action Filters. Here’s a filter example:

public class Handle404Attribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if(filterContext.Result is HttpNotFoundResult)
        {
            filterContext.HttpContext.Response.Redirect("~/Error/NotFound", true);
        }
    }
}

Alternatively, in ASP.NET Core, use the following approach:

public class HomeController : Controller
{
    [Route("{*url}", Order = int.MaxValue)]
    public IActionResult RouteNotFound()
    {
        return View("NotFound");
    }
}

Q4: Should I use global filters in ASP.NET MVC to catch and handle exceptions globally?

A4: Yes, utilizing global filters like HandleErrorAttribute allows you to catch unhandled exceptions and direct them to custom error pages. It’s defined in the Global.asax.cs file:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

Q5: How do I display a user-friendly message for a specific exception type?

A5: In ASP.NET Core, you can create a custom middleware to intercept specific types of exceptions and render a friendly view. Here’s a simple implementation:

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(httpContext, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        // Check exception type and redirect accordingly
        if(exception is InvalidOperationException)
        {
            context.Response.Redirect("/Error/InvalidOperation");
        }
        else
        {
            context.Response.Redirect("/Error/GeneralError");
        }
        return Task.CompletedTask;
    }
}

Q6: Why should I avoid using [HandleError] attributes directly over the actions in ASP.NET MVC?

A6: Overuse of [HandleError] attributes can lead to inconsistent error handling practices and make it harder to manage error logic across the application. It also won’t catch exceptions outside of controller actions or that occur in views.

Q7: Is it possible to show custom error messages during development without redirecting to an error page?

Q7: During development, keep the <customErrors> mode to “Off” to get detailed error messages, which are crucial for debugging. However, if redirection is still desired for testing purposes, you can create action methods that simulate errors and direct them to your error views.

Q8: How do I ensure that my custom error pages maintain the look and feel consistent with the rest of my application?

A8: Use partial views or layout views to ensure consistency across error pages. Inherit from a common base controller or use a custom error view model that contains navigation menus and other standard UI elements.

Q9: How can I log errors before displaying the custom error page?

A9: Log errors in the middleware or global exception filters before rendering the error page. For example, logging can be done using dependency injection in ASP.NET Core:

public class LoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public LoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
    {
        _next = next;
        _logger = loggerFactory.CreateLogger<LoggingMiddleware>();
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch(Exception e)
        {
            _logger.LogError($"Something went wrong: {e}");

            var code = HttpContext.Features.Get<IExceptionHandlerPathFeature>()?.StatusCode;
            context.Response.Redirect(code == null? "/Home/Error" : $"/Home/Error/{code}");
        }
    }
}

Q10: How should I deal with AJAX requests that return error pages?

A10: Customize your HandleExceptionAsync method to detect AJAX requests and respond appropriately. For example, returning JSON data with error information:

private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
    context.Response.ContentType = "application/json";
    return exception switch
    {
        UnauthorizedAccessException => context.Response.WriteAsync(new ErrorDetailsModel(401, "Unauthorized").ToString()),
        KeyNotFoundException => context.Response.WriteAsync(new ErrorDetailsModel(404, "Not Found").ToString()),
        _ => context.Response.WriteAsync(new ErrorDetailsModel(500, $"Oops! Something went wrong. Details: {exception.Message}").ToString()),
    };
}

In older MVC, you might check the request header X-Requested-With to identify AJAX requests and send back JSON instead.

You May Like This Related .NET Topic

Login to post a comment.