asp.net MVC exception Handling module Detailed _ Practical skills

Source: Internet
Author: User
Tags exception handling prepare system log wrapper

First, the preface

Exception handling is an essential part of every system that allows our programs to be friendly to prompt for errors, log error messages, and, more importantly, not disrupt normal data and affect system operations. Exception handling should be a pointcut, the so-called pointcuts are all parts will be used to it, regardless of which layer in the hierarchy, or the specific business logic module, the concern is the same. So, crosscutting concerns we will be unified in one place for processing. Both MVC and WebForm provide this implementation so that we can focus on exceptions.

In MVC, in Filterconfig, the default has been to help us register a handleerrorattribute, which is a filter that inherits the FilterAttribute class and implements the Iexceptionfilter interface. When it comes to exception handling , you will immediately associate 500 error pages, log logs, etc., Handleerrorattribute can easily customize the error page, the default is the error page, and log logs we just need to inherit it, and replace it with registration to globalfiltercollection. About Handleerrorattribute Many people know how to use, here is not to do the introduction.

OK, get to the theme! Dealing with exceptions in MVC, it is believed that many people are beginning to inherit Handleerrorattribute, 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, but a good design should be scene driven, dynamic and configurable. For example, in one scenario, we want Exceptiona to display error page A, and in scene two, we want it to display error page B, where the scene may be a cross project or a different module in the same system. In addition, the exception may be the classification, for example, when exceptiona occurs, we simply need to restore the state, the program can continue to run, exceptionb occurs, we want to record it to the file or system log, and Exceptionc occurs, is a more serious error, We want the program to take place by email or SMS notification. Simply put, different scenarios have different needs, and our programs need to be better faced with change. Of course, the inheritance Handleerrorattribute can also fully achieve the above mentioned, but here I do not intend to expand it, but to rewrite a module, and can be used with the original Handleerrorattribute common use.

Second, design and implementation

2.1 Defining configuration information

From the above we can already know what we want to do, for different exceptions, we want to be able to configure its handlers, error pages, and so on. As Next configuration:

<!--Custom exception configuration-->
<settingException>
 <exceptions>
  <!--Add priority is higher than group-->
  <add exception= "Exceptions.passworderrorexception"
     view = "Passworderrorview"
     handler= " Exceptionhandlers.passworderrorexceptionhandler "/>
  <groups>
   <!-- Group can configure an exception view and handler-->
   <group view= "Emptyerrorview" handler= " Exceptionhandlers.emptyexceptionhandler ">
    <add exception=" Exceptions.usernameemptyexception "/>
    <add exception= "exceptions.emailemptyexception"/>
   </group>    
  </groups>
 </exceptions>
</settingException>

Where the Add node is used to add a specific exception, its exception attribute is required, and view represents the error page, handler represents the specific handler, if view and handler are not, The exception is given to the default Handleerrorattribute processing. The group node is used for grouping, for example, the usernameemptyexception and emailemptyexception above correspond to the same handler and view.

The program reflects the reading of this configuration information and creates the corresponding object. We put this configuration file into the web.config to make sure it is ready to be changed at any time.

2.2 Exception Information Wrapper object

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

public class Exceptionconfig
{
  ///<summary>
  ///views
  ///</summary> public
  string View {get;set;}
 
  <summary>
  ///Exception Object
  ///</summary> public
  Exception exception{get;set;}
 
  <summary>
  ///Exception handler
  ///</summary> public
  iexceptionhandler handler{get;set;}

2.3 Define Handler Interface

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

Public interface Iexceptionhandler
{
  ///<summary>
  ///Exception processing complete
  ///</summary>
  bool Hashandled{get;set;}
 
  <summary>
  ///Processing exception
  ///</summary>
  ///<param name= "ex" ></param>
  void Handle (Exception ex);
}

All kinds of exception handlers can only implement this interface.

2.3 Implementation Iexceptionfilter

This is necessary. If you implement the Iexceptionfilter interface, Settingexceptionprovider gets the wrapper object from the configuration information (cache) based on the exception object type.

 public class Settinghandleerrorfilter:iexceptionfilter {public void onexception (E Xceptioncontext filtercontext) {if (Filtercontext = null) {throw new ArgumentNullException ("Filtercontex
    T ");
    } exceptionconfig config = Settingexceptionprovider.container[filtercontext.exception.gettype ()];
    if (config = = null) {return; } if (config. Handler!= null) {//execute Handle method CONFIG.
      Handler.handle (filtercontext.exception); if (config.
        handler.hashandled) {//exception handled, no follow-up action required filtercontext.exceptionhandled = true;
      Return }//Otherwise, if there is a custom page, the IF (!string) is displayed. IsNullOrEmpty (config.
      View) {//Here can also be extended to implement iview views Viewresult view = new Viewresult (); View. ViewName = config.
      View;
      Filtercontext.result = view;
      Filtercontext.exceptionhandled = true;
    Return //Otherwise the exception continues to be passed}} 

2.4 Read configuration file, create exception information wrapper object

This part of the code is more, in fact, you just know it is reading Web.config custom configuration node. Settingexceptionprovider is used to provide container objects.

public class Settingexceptionprovider {public static dictionary<type, exceptionconfig> Container = new Dicti
 
  Onary<type, exceptionconfig> ();
  Static Settingexceptionprovider () {Initcontainer (); ///Read configuration information, initialize container private static void Initcontainer () {var section = webconfigurationmanager.getsection ("Setti
    Ngexception ") 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> ()) {exceptionconfig config = new Exceptionconfig (); 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> ()) {exceptionconfig config = new Exceptionconfig (); Config. View = Item.
      View; Config. Handler = Createhandler (item.
      Handler); Config. Exception = CreateException (item.
      Exception); Container[config.
    Exception.gettype ()] = config; Create Iexceptionhandler object private static Iexceptionhandler Createhandler (string fullName) {I with fully qualified name F (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) based on the fully qualified name.
    IsNullOrEmpty (FullName)) {return null;
    Type type = Type.GetType (fullName); return Activator.CreateInstance (type) asException;
 }
}

The following are the information for 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 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 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;
    }
}}

Third, testing

OK, the following test, first of all, in the Filterconfig Registerglobalfilters method in, Handlererrorattribute before registering our filter:

Filters. ADD (New Settinghandleerrorfilter ()).

3.1 Preparing Exception objects

Prepare a few simple exception objects:

public class passworderrorexception:exception{} public
class usernameemptyexception:exception{}
Public Class emailemptyexception:exception{}

3.2 Prepare Handler

For the above exception, we prepared two handler, one to handle the password error exception, and one to handle the null exception. There is no actual processing code, concrete how to deal with, should be combined with specific business. Such as:

public class Passworderrorexceptionhandler:iexceptionhandler
{public
  bool Hashandled{get;set;}
   
  public void Handle (Exception ex)
  {
    //Concrete processing logic ...
  }
 
} public class Emptyexceptionhandler:iexceptionhandler
{public
  bool hashandled {get; set;}
 
  public void Handle (Exception ex)
  {
    //Concrete processing logic ...
  }
}

3.3 Throwing an exception

According to the above configuration, we manually throw the exception in 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 appear with our configured error page.

Iv. Summary

In fact, this is just a relatively simple example, so I call it a simple module, but the framework, library and other words. Of course, we can expand and optimize it according to the actual situation. Microsoft Enterprise Library Depending on the integration of such modules, interested friends can understand.

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.