异常的产生
在.net应用开发中,程序在运行时总会由于一些无法预料的、不合法的客观条件产生问题,抛出异常。如:在类型转换时,将一个非数字型字符转换为整形时;一个引用类型未进行初始化我们却调用它的方法或属性时;io操作时资源未准备好时;数据库操作时,db server无法访问、或者sql出错的时候,等等。
Asp.Net默认是怎么处理异常的
在产生异常的时候如果我们没有在自己的代码中捕获异常的话,应用程序会将异常信息交给asp.net runtime, 将将会抛出一个HttpUnhandledException异常。就是这个异常报给了我们经常看到的黄页信息。当然,它不只是会报黄页信息而已,也可以根据配置中的信息进行自定义异常页面。
在webconfig配置文件中,<customErrors>该节点定义了HttpUnhandledException这个类的处理行为。不同的行为依赖于customErrors节点的mode属性,共有下面三个属性:
- On 对所有用户展示自定义的错误页面或者一个Runtime Error的黄页,不包含错误的详细信息
- Off 对所有访问用户暴露出详细的错误信息
- RemoteOnly 对非本机用户暴露友好的错误信息。
当我们自定义错误页面的时候,可以这样<customErrors mode="On" defaultRedirect="~/error.aspx" />定义一个错误页面,也可以针对不同的异常类型指定不同的错误页面,如:
<customErrors mode="On" defaultRedirect="error.aspx"> <error statusCode="404" redirect="404.aspx"/> <error statusCode="500" redirect="500.aspx"/> </customErrors>
这样产生错误的时候就会根据不同的http码跳转到不同的页面了。
另补充一句:
- HttpUnhandledException在针对异常根据不同的配置进行跳转的时候是利用了
Response.Redirect()方法302跳转。
- 真对一些静态资源文件的404情况不会被处理,这些是被iis直接处理的。
404了我该做些什么
在发生404的时候有时是我们自己的站点链接写的不正确,或者是来自一些其他站点的错误外链,那么这个时候我们知道该链接来自哪里很重要,所以在404后跳转的页面中我们最好将发生了什么,在哪里发生的告诉自己,并及时的处理。开始在想这个问题的时候我还觉得用urlref获取不到错误页面的来源。后来发现在 Response.Redirect()方法302跳转的时候原始请求的一些信息也是附带过来的。所以打消了这个疑虑。这样我们就可以在404异常处理页面中记录异常来源通知自己了。另外来自一些外站的错误链接,我们不能等待他们修改,我们可以做个错误链接的映射,在404处理页面进行匹配处理。
404我们获取到死链接的来源了,那么我们如何获取到详细的错误信息呢?
一个问题是,当我们定义了友好的错误页面后,我们不能获取到详细的错误信息。如:在1.aspx页面发生了异常,将直接回跳转到500.aspx页面中,相当于2个请求,在新的请求当中(302跳转),我们是没有办法获取到前一个页面的信息的。下面看看针对这种情况我们如何处理它。
当一个未处理的异常抛给asp.net runtime时,会激发一个应用程序级别的异常事件,通过在这个事件中获取处理异常,我们可以记录日志,发邮件通知作者,用Server.Transfer()跳转到自定义的错误页面。Transfer不同于Redirect方法,它是在服务端的跳转,会携带着上下文信息,允许跳转的页面访问这些信息。;)
如何在应用程序级别的异常事件中处理异常
HttpApplication应用程序类中包含了一系列的asp.net web 应用程序事件,当一个未被处理的异常发生时就会激发该类的Error事件。在该事件中我们可以通过
Server.GetLastError()方法获取发生的异常对象。之后就可以进行异常信息的记录、通知等操作了。在此处我们获取的异常对象是HttpUnhandledException的实例,实际页面发生的异常被该对象封装在里面了,可以通过
InnerException属性获取到。
这样我们就可以捕获到应用程序发生的异常信息并且记录、发邮件啊之类的,之后在进行跳转到自定义的有好错误页面。
//获取到页面发生的异常对象 var error = Server.GetLastError(); if (error is HttpUnhandledException && error.InnerException != null) { error = error.InnerException; } try { //do something with error infomation } catch { } Server.Transfer("yourcustompage.aspx");
用HttpModule方式处理异常事件
为什么要用HttpModule的方式?
这种方式提供了一种更灵活的处理方法,我们可以简单的将dll放到bin目录并且改几句配置文件就可以加入我们的功能,非常灵活*。
开源日志库:ELMAH
参考文摘: