Exception handling in asp.net MVC

Time:2020-1-11

1、 Application scenario

For B / s applications, in the process of deployment to the formal environment for operation, there are likely to be some exceptions or errors not found in the early test process, or some exceptions only occur when certain conditions are met. For application sites developed with asp.net MVC, after deployment to IIS, if the developers do not handle the program errors, then Once there is an unhandled error or exception in the program, the user will see a confusing error stack trace page, which makes the user experience of the site decline. From the perspective of the program, it is not conducive to the root source search when the program has problems without user-defined error processing, because in many cases, some errors only reappear when the specific conditions are met, once missed, it may be It takes a lot of time to test to reproduce the problem. If the developer logs the runtime exception in the program at this time, it may provide some valuable information about the root cause of the error. Next, I will explain to you how to implement custom exception handling and jump to the friendly error prompt page.

2、 Exception handling & custom error page

1. Exception handling and custom error page through exception filter

Asp.net MVC provides an exception filter to catch unhandled exceptions when an action method in the controller is executed. The exception filter in MVC exists in the form of attribute. It only takes two steps to define a custom exception filter:

1. Define a class, inherit the filterattribute class, and implement iexceptionfilter interface 2. Apply the custom exception filter to the specified action method or controller class or global application.

Exception filter code

using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Blog20180413.Filters
{
 public class CustomExceptionFilterAttribute : FilterAttribute, IExceptionFilter
 {
 //Log4net component for logging.
 static readonly ILog log = LogManager.GetLogger(typeof(CustomExceptionFilterAttribute));
 public void OnException(ExceptionContext filterContext)
 {
  //Log the captured exception information for developers to troubleshoot.
  Log. Error ("application exception", filtercontext. Exception);

  //Jump to a custom error page to enhance the user experience.
  ActionResult result = new ViewResult() { ViewName = "CustomErrorPage" };
  filterContext.Result = result;
  //After exception handling, be sure to set exceptionhandled to true, otherwise the error will continue to be thrown.
  filterContext.ExceptionHandled = true;
 }
 }
}

Use exception filter

using Blog20180413.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Blog20180413.Controllers
{
 public class TestExceptionHandleController : Controller
 {
 [CustomExceptionFilter]
 public ActionResult Index()
 {
  string str = string.Empty;
  //Conversion exception will be thrown
  int result = int.Parse(str);
  return View();
 }
 }
}

Be careful:

As mentioned in the second step, you can only apply the custom exception filter to action or controller. If you want to apply the specified exception filter to one or more specified controllers or actions in the form of characteristics, rather than to all controllers or actions, you must inherit the filterattribute class. This is because the MVC framework uses the Filterattributefilterprovider.getfilters to get the exception filter attribute marked on the specified controller or action. The internal logic requirements of getfilters must inherit from the filterattribute class.

If you need to apply the custom exception filter to all controller actions, you need to register the custom exception filter to the global. The code is as follows:


using Blog20180413.Filters;
using System.Web;
using System.Web.Mvc;

namespace Blog20180413
{
 public class FilterConfig
 {
 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
  filters.Add(new CustomExceptionFilterAttribute());
 }
 }
}

2. Implement exception handling and custom error page by defining application error method in global.asax

The custom exception filter mentioned above can only catch exceptions thrown during the execution of the action method (even if registered as a global filter, it can only catch exceptions thrown during the execution of the action method). If you need to catch higher-level exceptions, that is, any exception occurred during the execution of the request (such as throwing an exception in the constructor of the controller), you can In this way, the code is as follows:

using log4net;
using log4net.Config;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Blog20180413
{
 public class MvcApplication : System.Web.HttpApplication
 {
  static readonly ILog log = LogManager.GetLogger(typeof(MvcApplication));
  protected void Application_Start()
  {
   AreaRegistration.RegisterAllAreas();
   FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
   RouteConfig.RegisterRoutes(RouteTable.Routes);
   XmlConfigurator.ConfigureAndWatch(new FileInfo(Server.MapPath("~/web.config")));
  }

  protected void Application_Error(object sender, EventArgs e)
  {
   Exception exception = Server.GetLastError();
   //Server.ClearError();
   //Error log information is recorded here
   Log. Error ("mvcaapplication catch exception", exception);
   //Jump to the specified custom error page
   Response.Redirect("/CustomErrorHandle/CustomErrorPage");
  }
 }
}

3. Realize the custom error page by configuring the system. Web – > customErrors node

When an exception occurs to your site, if you just want to jump to a user-defined error page instead of further handling the exception, you can simply do the following configuration operations:

You need to do the following configuration in web.config:


 <system.web>
  <customErrors mode="On" defaultRedirect="CustomErrorPage">
  </customErrors>
 </system.web>

Be careful:The customerrorpage here is a view file, which is placed in the shared directory.

If you register the handleerrorattribute exception filter to the global, you will get some information related to the exception in your error page. But at this time, the value configured to defaultredirect must be error

That is to say, the name of the custom error view page must be error.cshtml and placed in the shared directory. Of course, you can also set the view property of the handler during the process of creating the handleerrorattribute global filter, so that you can set the name of the error view to error without mentioning it. As follows:


 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
    HandleErrorAttribute errorAttribute = new HandleErrorAttribute();
    errorAttribute.View = "CustomErrorPage";
    filters.Add(errorAttribute);
 }

Register handleerrorattribute (use default error view page filename)


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

Define error.cshtml view page

@{
 Layout = null;
}
@model HandleErrorInfo
<!DOCTYPE html>
<html>
<head>
 <meta name="viewport" content="width=device-width" />
 <title>Error</title>
</head>
<body>
 <div>
  @*The exception information captured through the handleerrorattribute exception filter is stored in the model attribute*@
  @Model.Exception.Message
 </div>
</body>
</html>

The reason why the exception caught by registering the handleerrorattribute filter can get exception information in the error page can be seen in the internal implementation of the handleerrorattribute class. It is found that a handleerrorinfo object was passed in the process of loading the error view page.


public virtual void OnException(ExceptionContext filterContext)
{
 if (filterContext == null)
 {
  throw new ArgumentNullException("filterContext");
 }
 if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
 {
  Exception innerException = filterContext.Exception;
  if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
  {
   string controllerName = (string) filterContext.RouteData.Values["controller"];
   string actionName = (string) filterContext.RouteData.Values["action"];
   HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
   ViewResult result = new ViewResult {
    ViewName = this.View,
    MasterName = this.Master,
    ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
    TempData = filterContext.Controller.TempData
   };
   filterContext.Result = result;
   filterContext.ExceptionHandled = true;
   filterContext.HttpContext.Response.Clear();
   filterContext.HttpContext.Response.StatusCode = 500;
   filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
  }
 }
}

public string View
{
 get
 {
  if (string.IsNullOrEmpty(this._view))
  {
   return "Error";
  }
  return this._view;
 }
 set => 
  (this._view = value);
}

Three, summary

In general, the application error method is used to handle the exception errors at the request pipeline level, while the MVC exception filter can only handle the exceptions during the execution of the action method. The scope that can be handled is smaller than the application error, but in the actual project development, the use of the MVC exception filter to handle exceptions is relatively more, because our function business is often reflected During the execution of the action method of the controller, that is, during this process, it is easier to generate exceptions. Therefore, MVC exception filter can meet most of the needs of exception handling.

Well, the above is the whole content of this article. I hope that the content of this article has some reference learning value for your study or work. If you have any questions, you can leave a message and exchange. Thank you for your support for developepaer.