asp.net开发中常见公共捕获异常方式总结(附源码)

本文实例总结了asp.net开发中常见公共捕获异常方式。分享给大家供大家参考,具体如下:

前言:在实际开发过程中,对于一个应用系统来说,应该有自己的一套成熟的异常处理框架,这样当异常发生时,也能得到统一的处理风格,将异常信息优雅 地反馈给开发人员和用户。我们都知道,.net的异常处理是按照“异常链”的方式从底层向高层逐层抛出,如果不能尽可能地早判断异常发生的边界并捕获异 常,CLR会自动帮我们处理,但是这样系统的开销是非常大的,所以异常处理的一个重要原则是“早发现早抛出早处理”。但是本文总结的服务端公共捕获异常处 理可以宽泛地看做是在表现层的操作,要捕获特定层的特定异常,不在讨论范围内。

1、BasePage类处理方式

在页面的公共基类里重写OnError事件。在前面这篇《asp.net实现非常实用的自定义页面基类》里,楼猪已经贴了代码,就不再费事了。根据经验,很多人开发的时候几乎都这么写,而且对调试和维护还是很有帮助的。需要说明的是,每新添一个页面,其对应类都必须继承自BasePage类异常处理才起作用。

2、Global.asax处理方式

如1中所述,BasePage类的异常处理要求每一个aspx类文件都继承它,适用性和性能显然会打折扣。而Global.asax文件定义了 asp.net应用程序中的所有应用程序对象共有的方法、属性和事件,我们可以不采用BasePage的处理方式,在Global.asax里实现 Application_Error事件并处理也可以。下面模仿BasePage类里的处理异常方法,实现如下:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

/// <summary>

/// 出错处理:写日志,导航到公共出错页面

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

protected void Application_Error(object sender, EventArgs e)

{

  if (Server.GetLastError() == null) return;

  Exception ex = Server.GetLastError().GetBaseException();

  string error = this.DealException(ex);

  DotNet.Common.Util.Logger.WriteFileLog(error, HttpContext.Current.Request.PhysicalApplicationPath + "LogFile");

  if (ex.InnerException != null)

  {

    error = this.DealException(ex);

    DotNet.Common.Util.Logger.WriteFileLog(error, HttpContext.Current.Request.PhysicalApplicationPath + "LogFile");

  }

  this.Server.ClearError();

  this.Response.Redirect("/Error.aspx");

}

/// <summary>

/// 处理异常,用来将主要异常信息写入文本日志

/// </summary>

/// <param name="ex"></param>

/// <returns></returns>

private string DealException(Exception ex)

{

  this.Application["StackTrace"] = ex.StackTrace;

  this.Application["MessageError"] = ex.Message;

  this.Application["SourceError"] = ex.Source;

  this.Application["TargetSite"] = ex.TargetSite.ToString();

  string error = string.Format("URl:{0}\n引发异常的方法:{1}\n错误信息:{2}\n错误堆栈:{3}\n",

    this.Request.RawUrl, ex.TargetSite, ex.Message, ex.StackTrace);

  return error;

}

上面方式的好处是,写一次代码,应用程序发生的大部分异常它都给你捕捉处理了。楼猪要在这里由衷地发一番感慨,感谢ms为我们提供了这么优秀的框架,太省事了吧。

3、IHttpModule接口处理

1和2的处理方式大家都是非常熟悉的,楼猪在实际开发中基本上都是遵循上面两种写法,而且楼猪因为有了2中这种大小通吃的处理方式,甚至已经激动地 感谢ms了。但是,在asp.net程序调用线程进行异步处理的时候,容易发生在后台线程或线程池里抛出的异常并不能被1或(和)2完全捕捉到,这就涉及 到asp.net下未捕获异常的处理。也就是说楼猪以前做过的很多大小项目中对异常的处理是不完备的。这难道是nc楼猪没有先谢国家种下的恶果吗?感谢国 家,感谢ms,感谢博客园,感谢无私的xdjm,感谢自己......

asp.net下未捕获异常的处理步骤如下:

(1)、创建一个实现IHttpModule接口的类

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Text;

namespace DotNet.Common.WebForm

{

  using DotNet.Common.Util;

  /// <summary>

  /// 通用未捕获异常处理

  /// </summary>

  public class AspNetUnhandledExceptionModule : IHttpModule

  {

    static object syncObj = new object();

    static bool isInit = false;

    public AspNetUnhandledExceptionModule()

    {

    }

    #region IHttpModule Methods

    public void Init(HttpApplication context)

    {

      lock (syncObj)

      {

        if (!isInit)

        {

          AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);

          isInit = true;

        }

      }

    }

    public void Dispose()

    {

    }

    #endregion

    #region OnUnhandledException

    void OnUnhandledException(object o, UnhandledExceptionEventArgs e)

    {

      if (e.ExceptionObject == null) return;

      Exception ex = e.ExceptionObject as Exception;

      string error = string.Format("引发异常的方法:{0}\n错误信息:{1}\n错误堆栈:{2}\n",

              ex.TargetSite, ex.Message, ex.StackTrace);

      Logger.WriteFileLog(error, AppDomain.CurrentDomain.BaseDirectory + "LogFile");

    }

    #endregion

  }

}

(2)、web.config节点配置

?


1

2

3

<httpModules>

   <add name="AspNetUnhandledExceptionModule" type="DotNet.Common.WebForm.AspNetUnhandledExceptionModule, DotNet.Common.WebForm"></add>

</httpModules>

最后贴出测试代码:

?


1

2

3

4

5

6

7

8

9

10

11

12

protected void Page_Load(object sender, EventArgs e)

{

  if (!IsPostBack)

  {

    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Test), null);

  }

}

protected void Test(object state)

{

  int[] numArr = new int[100];

  numArr[100] = 100; //异常

}

需要说明的是,通过线程或者线程池处理的程序,在发生异常时,每个线程都会有它自己独立的上下文,所以HttpContext对象应尽可能少地出现在异常处理阶段。

小结:不知道还有多少童鞋认为异常处理就是在代码里try...catch一下,抛出异常然后完事?如果有的话,呵呵,当年楼猪是拿“没有人天生就 是十全十美的”这句话来安慰自己的。当然了,try...catch也不是不可以,只能说明我们对待异常的态度太草率了。为了显得我们的专业和全面,请参 考其他异常处理专业性文章研读一番,相比异常处理的核心思想(异常处理的“大智慧”),这篇文章总结的(异常处理的“小技巧”)对初学者而言可能也是误导 之作,请务必留意甄别。

完整实例代码代码点击此处本站下载

希望本文所述对大家asp.net程序设计有所帮助。

时间: 2024-10-23 11:52:38

asp.net开发中常见公共捕获异常方式总结(附源码)的相关文章

Android中常见Intent习惯用法-上篇(附源码下载)

Android中的Intent是一个非常重要的类,如果对Intent不是特别了解,可以参见博文<Android中Intent概述及使用>.如果对Intent Filter不是特别了解,可以参见博文<Android中Intent对象与Intent Filter过滤匹配过程详解>. 本文着重讲一下Android中一些常见的Intent的习惯用法,比如如何通过Intent发送短信.发送邮件.启动摄像机拍照录视频.设置闹铃.打开WIFI设置界面等等. 限于篇幅,本博文分为上下两篇,这是上篇

c++实现游戏开发中常用的对象池(含源码)

c++实现游戏开发中常用的对象池(含源码) little_stupid_child2017-01-06上传 对象池的五要素: 1.对象集合 2.未使用对象索引集合 3.已使用对象索引集合 4.当前使用量 5.最大使用量 http://download.csdn.net/download/little_stupid_child/9730912

C#/ASP.NET MVC微信公众号接口开发之从零开发(三)回复消息 (附源码)

C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发(二) 接收微信消息并且解析XML(附源码) 一.拼凑回复的XML字符串 微信被动回复的形式有一下六种: 1 回复文本消息 2 回复图片消息 3 回复语音消息 4 回复视频消息 5 回复音乐消息 6 回复图文消息 分别对应不同的XML形式,这里以文本消息和图文为例,读者举一反三其他的类似,不再赘述:

spring学习笔记2---MVC处理器映射(handlerMapping)三种方式(附源码)

一.根据Beanname访问controller: 在springmmvc-servlet.xml的配置handlermapping中加入beanname,通过该beanname找到对应的controller实现控制 1 <!-- 配置HandlerMapping 根据beanname找到对应Controller --> 2 <bean 3 class="org.springframework.web.servlet.mvc.support.ControllerBeanName

SwitchButton 开关按钮 的多种实现方式 (附源码DEMO)

http://blog.csdn.net/vipzjyno1/article/details/23707149 Switch开关android源码SwitchButton 刚开始接触开关样式的按钮是在IOS系统上面,它的切换以及滑动十分帅气,深入人心. 所谓的开关按钮,就是只有2个状态:on和off,下图就是系统IOS 7上开关按钮效果. 起初我在android上我只会使用CheckBox去满足对应的功能.后来,查看开发文档发现,android也有了自己的原生态开关控件,并且在4.0版本中又优化

Android中AIDL实现进程通信(附源码下载)

AIDL概述 之前的博客<Android中通过Messenger与Service实现进程间双向通信>演示了如何通过Messenger实现与Service进行跨进程通信,即IPC.但用Messenger实现的IPC存在一点不足:Service内部维护着一个Messenger,Messenger内部又维护着一个Hanlder,当多个client向该Service发送Message时,这些Message需要依次进入Hanlder的消息队列中,Hanlder只能处理完一个Message之后,再从消息队

mvc中AntiForgeryToken的实现方式--看Mvc源码

通过 AntiForgeryWorker的GetHtml()方法生成html --input hide元素--value=要验证的值,并生成cookie--用于保存需要验证的值. 类中的AntiForgeryDataSerializer--用作序列化与反序列化验证的值. internal class AntiForgeryWorker { public AntiForgeryWorker() { Serializer = new AntiForgeryDataSerializer(); } in

.Net中使用SendGrid Web Api发送邮件(附源码)

SendGrid是一个第三方的解决邮件发送服务的提供商,在国外使用的比较普遍.国内类似的服务是SendCloud.SendGrid提供的发送邮件方式主要是两种, 一种是SMTP API, 一种是Web Api. SMTP API是一种比较简单的方式,只要我们准备好Mail Message, 直接发送到SendGrid的邮件服务器就可以了,SendGrid的邮件服务器会帮我们投递.另外一种是Web Api的方式. 一般来说,很多三方的服务器提供商都会禁止链接外部25端口,这样你就没有办法连接Sen

【详解】嵌入式开发中固件的烧录方式

版本:v1.2 Crifan Li 摘要 本文主要介绍了嵌入式开发过程中,将固件从PC端下载到开发板中的各种方式,主要包括NFS挂载,Nand Flash和Nor Flash,USB,RS232,网卡NIC等方式. 本文提供多种格式供: 在线阅读 HTML HTMLs PDF CHM TXT RTF WEBHELP 下载(7zip压缩包) HTML HTMLs PDF CHM TXT RTF WEBHELP HTML版本的在线地址为: http://www.crifan.com/files/do