A simple ASP. net mvc Exception Handling Module, asp. netmvc Exception Handling

Source: Internet
Author: User

A simple ASP. net mvc Exception Handling Module, asp. netmvc Exception Handling

I. Preface

Exception Handling is an essential part of every system. It allows our programs to prompt and record error information in case of errors, more importantly, it does not damage normal data and affects system operation. Exception Handling should beCrosstab pointThe so-called cross-cutting point means that each part will use it. No matter which layer in the hierarchy or specific business logic module, it focuses on the same. Therefore, we will process the cross-cutting concerns in one place. Both MVC and WebForm provide this implementation, allowing us to handle exceptions in a centralized manner.

In MVC, in FilterConfig, A HandleErrorAttribute has been registered for us by default. This is a filter. It inherits the FilterAttribute class and implements the IExceptionFilter interface. For the filter execution process, see my view.PreviousArticle. When it comes to exception handling, we will immediately think of the 500 Error page, record logs, etc. handleerrorattri can easily customize the Error page, which is the Error page by default. To record logs, we only need to inherit it, and register it with GlobalFilterCollection. Many people know how to use HandleErrorAttribute.

OK. Start to enter the topic! Handle exceptions in MVC. I believe many people inherit HandleErrorAttribute from the beginning, and then rewrite the OnException method to add their own logic, such as writing exception information to log files. Of course, there is nothing wrong with this,However, a good design should be scenario-driven and dynamic and configurable.. For example, in the scenario, we want ExceptionA to Display error page A. in scenario 2, we want it to Display Error Page B. The scenario here may be cross-project, it may also be in different modules of the same system. In addition, exceptions may also be classified. For example, when tiona occurs, we only need to simply restore the status, the program can continue to run, and when ExceptionB occurs, we want to record it to a file or system log, and when ExceptionC occurs, it is a serious error. We want the program to receive an email or SMS notification. Simply put, different scenarios have different needs, and our program needsBetter face of changes. Of course, the inheritance of HandleErrorAttribute can fully implement the above mentioned, but here I do not intend to expand it, but re-compile a module and can be used together with the original HandleErrorAttribute.

Ii. Design and Implementation

2.1 define configuration information

We can see what we have to do from the above. For different exceptions, we hope to configure its processing program, error pages, and so on. As shown in the following Configuration:

<! -- Custom exception configuration --> <settingException> <exceptions> <! -- Add has a higher priority than group --> <add exception = "Exceptions. PasswordErrorException" view = "PasswordErrorView" handler = "ExceptionHandlers. PasswordErrorExceptionHandler"/> <groups> <! -- Group can configure an abnormal view and handler --> <group view = "EmptyErrorView" handler = "ExceptionHandlers. emptyExceptionHandler "> <add exception =" Exceptions. userNameEmptyException "/> <add exception =" Exceptions. emailEmptyException "/> </group> </groups> </exceptions> </settingException>

The add node is used to add specific exceptions. Its exception attribute is required, while view indicates the error page, and handler indicates the specific handler. If neither view nor handler is available, the exception is handled by HandleErrorAttribute by default. The group node is used for grouping. For example, the preceding UserNameEmptyException and EmailEmptyException correspond to the same handler and view.

The program will read the configuration information and create an object. We put this configuration file in Web. config to ensure that it can take effect at any time.

2.2 exception information packaging object

Here we define an object that corresponds to the above node. As follows:

Public class ExceptionConfig {// <summary> /// View // </summary> public string View {get; set ;} /// <summary> /// Exception object /// </summary> public Exception {get; set ;} /// <summary> /// exception handling program /// </summary> public IExceptionHandler Handler {get; set ;}}

2.3 define the Handler Interface

As mentioned above, different exceptions may require different processing methods. Here we design an interface as follows:

Public interface IExceptionHandler {// <summary> /// whether the exception is handled completely /// </summary> bool HasHandled {get; set ;} /// <summary> /// Handle the Exception /// </summary> /// <param name = "ex"> </param> void Handle (Exception ex );}

All kinds of exception handling programs only need to implement this interface.

2.3 implement IExceptionFilter

This is required. Implement the IExceptionFilter interface as follows. SettingExceptionProvider obtains the packaging object from the configuration information (cache) based on the exception object type.

Public class exception: IExceptionFilter {public void OnException (ExceptionContext filterContext) {if (filterContext = null) {throw new ArgumentNullException ("filterContext");} ExceptionConfig = SettingExceptionProvider. container [filterContext. exception. getType ()]; if (config = null) {return;} if (config. handler! = Null) {// execute the Handle method config. handler. handle (filterContext. exception); if (config. handler. hasHandled) {// The exception has been handled, and subsequent filterContext operations are not required. exceptionHandled = true; return ;}// otherwise, if a custom page exists, if (! String. isNullOrEmpty (config. view) {// here you can also extend it to view ViewResult view = new ViewResult (); View. viewName = config. view; filterContext. result = view; filterContext. exceptionHandled = true; return;} // otherwise, the exception will be passed on }}

2.4 read the configuration file and create an exception information packaging object

In fact, you only need to know that the code is reading the custom configuration node of web. config. SettingExceptionProvider is used to provide container objects.

Public class SettingExceptionProvider {public static Dictionary <Type, ExceptionConfig> Container = new Dictionary <Type, ExceptionConfig> (); static SettingExceptionProvider () {InitContainer () ;}// read configuration information, initialize the private static void InitContainer () {var section = WebConfigurationManager. getSection ("settingException") as SettingExceptionSection; if (section = null) {return;} InitFromGroups (section. exceptions. groups); InitFromAddCollection (section. exceptions. addCollection);} private static void InitFromGroups (GroupCollection groups) {foreach (var group in groups. cast <GroupElement> () {predictionconfig config = new predictionconfig (); config. view = group. view; config. handler = CreateHandler (group. handler); foreach (var item in group. addCollection. cast <AddElement> () {Exception ex = CreateException (item. exception); config. exception = ex; Container [ex. getType ()] = config ;}} private static void InitFromAddCollection (AddCollection collection) {foreach (var item in collection. cast <AddElement> () {predictionconfig config = new predictionconfig (); config. view = item. view; config. handler = CreateHandler (item. handler); config. exception = CreateException (item. exception); Container [config. exception. getType ()] = config ;}}// create the IExceptionHandler object private static IExceptionHandler CreateHandler (string fullName) {if (string. isNullOrEmpty (fullName) {return null;} Type type = Type. getType (fullName); return Activator. createInstance (type) as IExceptionHandler;} // create the Exception object private static Exception CreateException (string fullName) {if (string. isNullOrEmpty (fullName) {return null;} Type type = Type. getType (fullName); return Activator. createInstance (type) as Exception ;}}

The following is the information about each configuration node:

SettingExceptions node:

/// <Summary> /// settingExceptions node // </summary> public class SettingExceptionSection: ConfigurationSection {[ConfigurationProperty ("exceptions", IsRequired = true)] public ExceptionsElement Exceptions {get {return (ExceptionsElement) base ["exceptions"] ;}}

Exceptions node:

/// <Summary> /// exceptions node /// </summary> public class ExceptionsElement: ConfigurationElement {private static readonly ConfigurationProperty _ addProperty = new ConfigurationProperty ("", typeof (AddCollection), null, ConfigurationPropertyOptions. isDefaultCollection); [ConfigurationProperty ("", IsDefaultCollection = true)] public AddCollection {get {return (AddCollection) base [_ addProperty];} [ConfigurationProperty ("groups")] public GroupCollection Groups {get {return (GroupCollection) base ["groups"] ;}}

Group node set:

/// <Summary> /// group node set /// </summary> [ConfigurationCollection (typeof (GroupElement), AddItemName = "group")] public class GroupCollection: configurationElementCollection {/* override */protected override ConfigurationElement CreateNewElement () {return new GroupElement ();} protected override object GetElementKey (ConfigurationElement element) {return element ;}}

Group node:

/// <Summary> // group node // </summary> public class GroupElement: ConfigurationElement {private static readonly ConfigurationProperty _ addProperty = new ConfigurationProperty ("", typeof (AddCollection), null, ConfigurationPropertyOptions. isDefaultCollection); [ConfigurationProperty ("view")] public string View {get {return base ["view"]. toString () ;}} [ConfigurationProperty ("handler")] public string Handler {get {return base ["handler"]. toString () ;}} [ConfigurationProperty ("", IsDefaultCollection = true)] public AddCollection {get {return (AddCollection) base [_ addProperty] ;}}

Add node set:

/// <Summary> /// add node set /// </summary> public class AddCollection: ConfigurationElementCollection {/* override */protected override ConfigurationElement CreateNewElement () {return new AddElement ();} protected override object GetElementKey (ConfigurationElement element) {return element ;}}

Add node:

/// <Summary> /// add node /// </summary> public class AddElement: ConfigurationElement {[ConfigurationProperty ("view")] public string View {get {return base ["view"] as string ;}} [ConfigurationProperty ("handler")] public string Handler {get {return base ["handler"] as string ;}} [ConfigurationProperty ("exception", IsRequired = true)] public string Exception {get {return base ["exception"] as string ;}}}

 

Iii. Test

OK. Let's test it. First, register our filter before handlererrorattriters IN THE RegisterGlobalFilters method of FilterConfig:

Filters. Add (new SettingHandleErrorFilter ()).

3.1 prepare the exception object

Prepare several simple exception objects:

 public class PasswordErrorException : Exception{} public class UserNameEmptyException : Exception{}  public class EmailEmptyException : Exception{}

3.2 prepare Handler

For the above exception, we prepare two Handler, one for Password error exception handling and the other for null exception handling. There is no actual processing code here. How to Deal with it should be combined with specific services. For example:

Public class PasswordErrorExceptionHandler: IExceptionHandler {public bool HasHandled {get; set;} public void Handle (Exception ex) {// specific processing logic ...}} public class EmptyExceptionHandler: IExceptionHandler {public bool HasHandled {get; set;} public void Handle (Exception ex) {// specific processing logic ...}}

3.3 throw an exception.

According to the above configuration, we manually throw an exception in the Action

        public ActionResult Index()        {            throw new PasswordErrorException();        }        public ActionResult Index2()        {            throw new UserNameEmptyException();        }        public ActionResult Index3()        {            throw new EmailEmptyException();        }

As you can see, the corresponding Handler will be executed, and the browser will also display our configuration error page.

Iv. Summary

In fact, this is just a simple example, so I call it a simple module, but it uses words like frameworks and libraries. Of course, we can expand and optimize it according to the actual situation. The Microsoft enterprise database is integrated with such a module. If you are interested, you can find out.

Source code download

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.