首先我们建立自己的异常类CustomException,它要继承自ApplicationException类(这是一个在发生非致命的应用程序错误时抛出的通用异常,它又继承于更为通用的Exception类),将其用作为应用程序定义的任何自定义异常的基类。通过这个基类,我们就可以编写一个通用的catch代码块,捕获应用程序定义的任何自定义异常类型。
自定义的异常类型可以在这中间扮演一个非常重要的角色。我们可以捕获一个通用的异常,识别它和应用程序的关系,然后把它作为特定于应用程序的异常再次抛出,以便能适当地处理它。
这里构建了一个简单的场景,使用Northwind数据库,向其中添加一条Customer记录,如果ID重复则抛出相应的异常信息。
(1) 定义我们的基础异常类
public class CustomException:ApplicationException
{
public CustomException()
{
}
public CustomException(string message, Exception inner):base(message,inner)
{
}
}
定义两个处理异常的方法,使用base关键字让CustomException方法继承自基本的错误异常类ApplicationException并提供了两个参数,一个异常消息参数和一个异常错误类。
(2) 然后我们再定一个处理我们不同自定义错误类型的错误处理类,不同的应用程序异常类型使用不同的异常处理类。
public class DuplicateCustomerIDException : CustomException
{
public DuplicateCustomerIDException()
{
}
public DuplicateCustomerIDException(string message, Exception inner):base(message,inner)
{
}
}
当出现相应类型的异常时,在这个自定义异常处理中可以在出现错误的时候做一系列的处理,然后再抛出异常信息,例如:记录错误日志,或者做容错处理等。
(3) 最后我们在添加客户记录的时候,使用我们自定义的异常
private void AddCustomerRecord()
{
SqlConnection cn = new SqlConnection(DBConn);
cn.Open();
try
{
SqlCommand com = new SqlCommand("Insert Into Customers (CustomerID,CompanyName,ContactName) Values ('"+ftxt_CustomerID.Text+"','"+ftxt_CompanyName.Text+"','"+ftxt_ContactName.Text+"')",cn);
com.ExecuteNonQuery();
}
catch(SqlException ex)
{
if(ex.Number == 2627)
{
throw new DuplicateCustomerIDException("CustomerID重复",ex);
}
else
{
MessageBox.Show("成功","提示信息",MessageBoxButtons.OK,MessageBoxIcon.Information,MessageBoxDefaultButton.Button1,MessageBoxOptions.DefaultDesktopOnly);
}
}
finally
{
cn.Close();
}
}
其中的ex.Number == 2627就是由于数据表中主键重复不能添加重复主键的记录时抛出的异常号码,如果异常类型符合怎抛出我们自定义的异常处理类。
(4) 最后我们在调用这个方法时,编写代码捕获这个我们自定义类型的异常
private void fbtn_Submit_Click(object sender, System.EventArgs e)
{
try
{
AddCustomerRecord();
}
catch(DuplicateCustomerIDException ex)
{
MessageBox.Show(ex.Message);
}
}
For Example :
private void AddCustomerRecord()
{
SqlConnection cn = new SqlConnection(DBConn);
cn.Open();
try
{
SqlCommand com = new SqlCommand("Insert Into Customers (CustomerID,CompanyName,ContactName) Values ('"+ftxt_CustomerID.Text+"','"+ftxt_CompanyName.Text+"','"+ftxt_ContactName.Text+"')",cn);
com.ExecuteNonQuery();
}
catch(SqlException ex)
{
if(ex.Number == 2627)
{
throw new Exception ("CustomerID重复");
}
else
{
MessageBox.Show("成功","提示信息",MessageBoxButtons.OK,MessageBoxIcon.Information,MessageBoxDefaultButton.Button1,MessageBoxOptions.DefaultDesktopOnly);
}
}
finally
{
cn.Close();
}
}
捕获
try
{
AddCustomerRecord();
}
catch(Exception ex)
{
MessageBox.Show(ex.InnerException.Message);
}
以XML为错误信息资源的自定义异常处理
1、先做个xml,用来存储异常信息。文件名:MsgsResource.xml
<?xml version="1.0" encoding="utf-8" ?>
<messages>
<message id="0">
<title>数据提供问题</title>
<body>没有找到数据的提供地方</body>
</message>
<message id="1">
<title>
地址
错误</title>
<body>页面地址错误或者地址参数错误</body>
</message>
</messages>
2、再做一个用来存msgs的用来存title和body的构造体,类名为CustomExceptionType.cs
public class ExceptionMsg
{
private int messageid=-1;
private string title="";
private string body="";
public int MessageId
{
get { return messageid; }
set { messageid=value; }
}
public string Title
{
get { return title; }
set { title=value; }
}
public string Body
{
get { return body; }
set { body=value; }
}
}然后再做个读xml的类,这个类要传个id的参数进去作为查找。类名:ExceptionMsgsManager.cs
public ExceptionMsgsManager()
{
//如果Cache为空的话才
执行
if (HttpRuntime.Cache["ExceptionMsgs"] == null)
{
Hashtable MsgsTable=new Hashtable();//定义一个哈希表用来存储错误信息的集合
ExceptionMsg em;
XmlDocument doc=new XmlDocument();
string XmlPath=HttpContext.Current.Server.MapPath("MsgsResource.xml");
doc.Load(XmlPath);
XmlNode UrlsRoot=doc.SelectSingleNode("messages");
foreach (XmlNode node in UrlsRoot.ChildNodes)
{
em=new ExceptionMsg();
//用数据构造体装载xml的
内容
em.MessageId=int.Parse(node.Attributes["id"].Value);
em.Title=node.SelectSingleNode("title").InnerText;
em.Body=node.SelectSingleNode("body").InnerText;
//将填充好的em加载到哈希表里
MsgsTable[em.MessageId]=em;
}
//将完整的哈希表插入到Cache
HttpRuntime.Cache.Insert("ExceptionMsgs", MsgsTable , null, DateTime.MaxValue, TimeSpan.Zero);
}
}
/** <summary>
/// 读取异常信息的Hashtable
/// </summary>
/// <param name="MessageId">这个是xml中的messageid</param>
/// <returns></returns>
public ExceptionMsg GetExceptionMsg(int MessageId)
{
Hashtable Msgs=(Hashtable)HttpRuntime.Cache["ExceptionMsgs"];
return (ExceptionMsg)Msgs[MessageId];
}
3、做一个
友好
的界面,也就是做一个输出错误信息的页,pageload的事件里就request出地址参数,文件名:WebForm1.aspx
private void Page_Load(object sender, System.EventArgs e)
{
int msgid=int.Parse(Request["msgid"]);
//GetExceptionMsg我将他做成了静态方法,大家可以自己做一个静态方法,且这个页很
简单
,我就不详细写了
Response.Write(GetExceptionMsg(msgid).Title);
Response.Write("<br>");
Response.Write(GetExceptionMsg(msgid).Body);
}
4、关键的东西开始了~要认真看哦,首先自定义一个异常的枚举类型,类型名:CustomExceptionType.cs
public enum CustomExceptionType
{
DataProvider = 0,//数据提供错误
PageUrlError = 1//地址错误
}
5、然后要写一个自定义的异常处理类,在这个类的重写方法全用自定义的异常类型,这个类
继承
了ApplicationException,再多态了一下。(这个我想是写注析的,但后来不知道怎样写好,只会让大家意会了)
类名:CustomException.cs
public class CustomException : ApplicationException
{
成员#region 成员
CustomExceptionType exceptionType;
public CustomExceptionType ExceptionType
{
get
{
return exceptionType;
}
}
#endregion
构造函数#region 构造函数
public CustomException(CustomExceptionType t) : base()
{
Init();
this.exceptionType = t;
}
public CustomException(CustomExceptionType t, string message) : base(message)
{
Init();
this.exceptionType = t;
}
public CustomException(CustomExceptionType t, string message, Exception inner) : base(message, inner)
{
Init();
this.exceptionType = t;
}
#endregion
重写的方法#region 重写的方法
public override string Message
{
get
{
// 具体处理可以放在这里
// switch (exceptionType)
// {
// case CustomExceptionType.UserNotFound:
// return string.Format(ResourceManager.GetString("Exception_UserNotFound"), base.Message);
// }
return base.Message;
}
}
public override int GetHashCode()
{
string stringToHash = ( exceptionType + base.Message);
return stringToHash.GetHashCode();
}
#endregion
错误产生的属性#region 错误产生的属性
string userAgent = string.Empty;
public string UserAgent
{
get { return userAgent; }
set { userAgent = value; }
}
public int Category
{
get { return (int) exceptionType; }
set { exceptionType = (CustomExceptionType) value; }
}
string ipAddress = string.Empty;
public string IPAddress
{
get { return ipAddress; }
set { ipAddress = value; }
}
string httpReferrer = string.Empty;
public string HttpReferrer
{
get { return httpReferrer; }
set { httpReferrer = value; }
}
string httpVerb = string.Empty;
public string HttpVerb
{
get { return httpVerb; }
set { httpVerb = value; }
}
string httpPathAndQuery = string.Empty;
public string HttpPathAndQuery
{
get { return httpPathAndQuery; }
set { httpPathAndQuery = value; }
}
DateTime dateCreated;
public DateTime DateCreated
{
get { return dateCreated; }
set { dateCreated = value; }
}
DateTime dateLastOccurred;
public DateTime DateLastOccurred
{
get { return dateLastOccurred; }
set { dateLastOccurred = value; }
}
int frequency = 0;
public int Frequency
{
get { return frequency; }
set { frequency = value; }
}
string stackTrace = string.Empty;
public string LoggedStackTrace
{
get
{
return stackTrace;
}
set
{
stackTrace = value;
}
}
int exceptionID = 0;
public int ExceptionID
{
get
{
return exceptionID;
}
set
{
exceptionID = value;
}
}
#endregion
异常产生后要做的事情#region 异常产生后要做的事情
private void Init()
{
//这里暂时为空,要用到的时候再写
}
#endregion
}
6、在Global.asax的Application_Error中做抛出错误后的处理
//先判断是否为自己定义的异常
if(Server.GetLastError().GetBaseException() is CustomException)
{
//把抛出的异常的信息读出来
CustomException ce=(CustomException)Server.GetLastError().GetBaseException();
//带上异常信息的ID跳到错误页
Response.Redirect("webform1.aspx?msgid="+ce.ExceptionID,true);
}
7、最后的一步....测试
try
{
//随便写点东西
SqlConnection conn=........;
conn.Open();
}
catch
{ //没什么好说的,就是势出刚才的劳动成果
throw new CustomException(CustomExceptionType.DataProvider) ;
}