ASP. NET MVC Error Handling Corresponding Solution

  • 2021-10-24 22:42:42
  • OfStack

Error handling for ASP. NET MVC should take into account errors that occur during model binding, failure to route to a specified operation, and error handling for the controller. Using configuration files can help us handle exceptions, but it is not flexible and comprehensive enough; Using the HandleErrorAttribute, custom error filters, or override controller OnException methods can only resolve errors against the controller, not errors that occur during model binding, or 404 errors, even if the error filters are registered as global filters. Sometimes multiple methods are needed together.

Where errors are caught, useful information can be recorded, which is convenient for us to find out the cause of the problem and correct the error.

1 Enable custom errors

When using this method 1, you must pay attention to setting defaultRedirect to the specified error page to prevent hackers from detecting various error situations and then discovering the amount of vulnerabilities in the system.


<system.web>
 <customErrors mode="On" defaultRedirect="/error/error2">
  <error statusCode="404" redirect="/error/error1" />
 </customErrors>
 <!-- Other configurations -->
</system.web>

Mode: Processing mode, there are 3 processing modes

On, which enables custom processing and displays a custom error page when an error occurs Off, turn off custom error handling and display the default error page when an error occurs. RemoteOnly, which enables custom error handling, but only for requests from remote machines.

defaultRedirect: When an error occurs, the specified error page is displayed.

< error > Displays the specified error page based on the status code. mode must be in On or RemoteOnly mode, otherwise it will not work.

Note: Both defaultRedirect and redirect are configured for the specified path, such as the controller error in the above configuration, the controller operations are error1 and error2, and the corresponding error pages are Error1. cshtml and Error2. cshtml.

2 Error handling for controllers

2.1 Decorate the controller or operation with HandleErrorAttribute.


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    // Gets or sets the type of exception. 
    public Type ExceptionType { get; set; } 
    // Gets or sets the master view used to display exception information 
    public string Master { get; set; }
    // Gets the only 1 Identifier. 
    public override object TypeId { get; }
    // Gets or sets the page view used to display exception information. 
    public string View { get; set; }
    // Called when an exception occurs.  
    //filterContext: Action filter context 
    public virtual void OnException(ExceptionContext filterContext);
}

Example:

When an exception of type KeyNotFoundException occurs, the KeyNotFind view is displayed


[HandleError(ExceptionType=typeof(KeyNotFoundException),View="KeyNotFound")]
public ActionResult Index()
{
  ......
}

You can also use custom error filters and apply them to controllers or actions.

Example:


public class CustomHandleError : HandleErrorAttribute
  {
    public override void OnException(ExceptionContext filterContext)
    {
      if (filterContext==null)
        base.OnException(filterContext);

      // Record a log 
      LogError(filterContext.Exception);

      // Determine whether custom errors are enabled 
      if (filterContext.HttpContext.IsCustomErrorEnabled)
      {
        // Set Error to Handled 
        filterContext.ExceptionHandled = true;
        base.OnException(filterContext);
      }
    }
  }

You can set up a global filter, which works for every 1 controller.

Global error filters are set in the FilterConfig. cs file under the App_Start folder, and the filters are executed in the order in which they are registered. However, you can specify the execution order through the Order attribute.

Example:


public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      filters.Add(new HandleErrorAttribute 
      {
        ExceptionType = typeof(KeyNotFoundException),
        View = "KeyNotFound",
        Order = 2
      });
      filters.Add(new HandleErrorAttribute(),1);
    }
}

Set the custom error filter as a global filter:

In the file FilterConfig. cs under the App_Start folder

Example:


public class FilterConfig
  {
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      
       // Other filters 

       filters.Add(new CustomHandleError());
     }
   }

2.2 Rewrite controller OnException method

Be careful to set the error to handled or the error will continue to be thrown, but if you set the global error filter, it doesn't matter even if you don't mark it as handled, because the error will eventually be caught and handled by the global filter.

Example:


public class HomeController : Controller
 {

    // Other controller operations 

    protected override void OnException(ExceptionContext filterContext)
    {
      if (filterContext==null)
        base.OnException(filterContext);

      // Record a log 
      LogError(filterContext.Exception);

      // Determine whether custom errors are enabled 
      if (filterContext.HttpContext.IsCustomErrorEnabled)
      {
        // Set Error to Handled 
        filterContext.ExceptionHandled = true;
        // Display error page 
      this.View("Error").ExecuteResult(this.ControllerContext);
      }
    }
}

Or create a controller base class


public class BaseController : Controller
  {
    protected override void OnException(ExceptionContext filterContext)
    {
      // Error logging 
    }
  }

3 Global Error Handling

We can only use global error handling strategies for exceptions thrown during model binding or routing.

3.1 Adding code to handle exceptions in Global. asax

Example:


 public class MvcApplication : System.Web.HttpApplication
  {
    protected void Application_Start()
    {
      AreaRegistration.RegisterAllAreas();
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
      RouteConfig.RegisterRoutes(RouteTable.Routes);
      BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

    protected void Application_Error(object sender, EventArgs e)
    {
      var exception = Server.GetLastError();
      if (exception == null)
      {
        return;
      }

      // Log an exception or send a message 

      // Clear exception 
      Server.ClearError();

      // Redirect 
      Response.Redirect("home/index");
    }
  }

3.2 Capture Unmatched Routes

Register the route at the bottom of the route registration list.


public class RouteConfig
  {
    public static void RegisterRoutes(RouteCollection routes)
    {
      // Other configurations 
      routes.MapRoute(
        name: "MatchAll",
        url: "{*anyurl}",
        defaults: new { controller = "Error",action ="Missing" }
        );
     }
   }

Define Error controller and Missing operation


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    // Gets or sets the type of exception. 
    public Type ExceptionType { get; set; } 
    // Gets or sets the master view used to display exception information 
    public string Master { get; set; }
    // Gets the only 1 Identifier. 
    public override object TypeId { get; }
    // Gets or sets the page view used to display exception information. 
    public string View { get; set; }
    // Called when an exception occurs.  
    //filterContext: Action filter context 
    public virtual void OnException(ExceptionContext filterContext);
}
0

It should be noted that this method can handle all mismatches.

For example: http://localhost/mvcpointapp/home/index1. This url request says that my home exists, but the index1 operation does not exist. The MatchAll route configured above cannot match this url.

Matchable scenarios are: http://localhost/mvcpointapp/v1/home/index/1. This url can be matched by the MatchAll route configured above, so the Missing view can be displayed.

4 Practice

4.1 When using HandleErrorAttribute, pay attention to the < system.web > Adj. < customErrors > Section.

For example:

The controller is


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    // Gets or sets the type of exception. 
    public Type ExceptionType { get; set; } 
    // Gets or sets the master view used to display exception information 
    public string Master { get; set; }
    // Gets the only 1 Identifier. 
    public override object TypeId { get; }
    // Gets or sets the page view used to display exception information. 
    public string View { get; set; }
    // Called when an exception occurs.  
    //filterContext: Action filter context 
    public virtual void OnException(ExceptionContext filterContext);
}
1

< system.web > Adj. < customErrors > Section

< customErrors mode="On" defaultRedirect="Error/Error2" > < /customErrors >

The Error. cshtml file is located under the Shared folder, a subfolder under the Views folder

Enter in the browser: http://localhost/mvcpointapp/

As a result, the Error. cshtml page appears normally, noting that although defaultRedirect is specified in the customErrors configuration section, you jump to the Error. cshtml page.

Will < customErrors > mode of is set to Off, the classic error page is displayed.

4.2 Application_Error

The code is shown in section 3.1, the controller is shown in section 4.1, < system.web > Adj. < customErrors > Section is < customErrors mode="On" defaultRedirect="Error/Error2" > < /customErrors >

Input: http://localhost/mvcpointapp/home/index, breakpoint debugging, found that the error was intercepted by HandleError, and Application_Error method of Global. asax was not executed. When input: http://localhost/mvcpointapp/home/indexr, Application_Error is executed.

Shut down < customErrors > Configure the section without dropping the HandleErrorAttribute feature on the controller, enter: http://localhost/mvcpointapp/home/index, and find Application_Error executed.

Through the above practice, it is fully proved that HandleErrorAttribute can intercept the exception thrown in the controller, but cannot intercept the exception that resources cannot be found.

4.3 Strategies

One common strategy for intercepting error messages, logging errors, and displaying custom error pages is:

1) Configure first < system.web > Adj. < customErrors > Section, note that defaultRedirect; must be set; And define error controllers and corresponding actions and views.

2) Define a base class controller or a custom error filter to log exceptions. For case 1 of a custom error filter, register it as a global filter.

3) Add the Application_Error method to Global. asax to intercept unexpected exceptions and log them.

Reference:

1. Jess Chadwick/Todd Snyder/Hrusikesh Panda, Xu Lei/Xu Yang

Translate. ASP. NET MVC4 Web Programming

2. Jon Galloway/Phil Haack/Brad Wilson/K. Scott Allen, Sun Yuanshuai/Zou Quan Translated ASP. NET MVC4 Advanced Programming (4th Edition)

3. Huang Baomong, ASP. NET MVC4 Development Guide

4. Jiang Jinnan, ASP. NET MVC4 Framework Secret

5.https://www.asp.net/mvc

6. Dino Esposito, translated by Pan Lichen, ASP. NET MVC5 programming practice


Related articles: