一个让用户满意的程序不是不会出错,而是出错之后仍然给用户留下一丝温馨的感觉;
一个远见卓识的程序猿,肯定会给自己留条后路来保持程序的扩展性;
一个少挨骂维护猿的程序,肯定是针对错误有着良好的处理;
无论你是用户还是负责人;无论你是开发人猿还是维护人猿;
处理好程序中的错误,彰显程序的美好的一面是我们共同的愿望,好比一只孔雀,把自己美丽的一面展现出来,既满足了别人也舒适了自己,何乐为不为?
好吧,意识到错误处理的魅力后,就让我们走进Ajax的容错处理!
一、错误的通用设置
说到通用设置,第一反应就是去配置文件中设置。
<!--错误页配置--> <customErrors mode="On" defaultRedirect="~/Error.aspx"></customErrors>
除了在Web.config文件中修改customErrors配置节的属性为On外,还需要在aspx页面的ScriptManager(脚本统一管理)添加相应的属性。<%--错误页配置--%> <asp:ScriptManager ID="ScriptManager1" runat="server" AllowCustomErrorsRedirect="true"> </asp:ScriptManager>
如果从程序的整体来看,web.config文件好比是公路上的路标,指示每部程序(相当于是一部car)怎么走;每一个aspx页面相当于一个收费站,如果想要通过页面显示出既定的错误,那么就需要得到收费站的管卡,而页面中的ScriptManager,俗称脚本统一管理器,AllowCustomErrorsRedirect的属性就是起到管卡的作用。
经过上面两道管卡,我们就可以在处理程序的界面中,添加抛出异常的代码就可以将已经定义好错误处理页Error.aspx显示出来了,配置文件中要注意路径的填写。
protected void Button1_Click(object sender, EventArgs e) { //抛出异常 throw new Exception(); }
二、自定义错误
如果一个程序没有自定义的错误,谈何程序的魅力?在程序中添加自定义错误,既可以给客户以舒适(至少不反感)的体验还可以给开发和维护人员以相应的提示。这才算是一种比较好的做法。
那么,在Ajax中怎么自定义错误呢?
简单的总结了两种方法,一种是从客户端发起的错误处理,另一种是在服务器端定义的错误处理。
1、从客户端发起的错误处理
首先,关掉ScriptManager的AllowCustomErrorsRedirect属性,然后在它的OnAsyncPostBackError属性中指明异步刷新的事件。
<%--AllowCustomErrorsRedirect属性设置为false,配合后台的自定义错误使用--%> <asp:ScriptManager ID="ScriptManager1" runat="server" AllowCustomErrorsRedirect="false" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"> </asp:ScriptManager>
然后,在页面的C#后台添加自定义的错误信息和异步刷新事件中要显示的错误信息。protected void Button1_Click(object sender, EventArgs e) { //自定义错误处理,配合web.config文件中的错误配置节点customErrors(设置为on的时候才生效,同时还要制定错误页)和AllowCustomErrorsRedirect(是否允许customErrors)使用 throw new Exception("Custom Error!"); } //异步刷新出现错误时,触发的事件 protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) { //客户端接受到的错误的信息 ScriptManager.GetCurrent(this).AsyncPostBackErrorMessage = e.Exception.Message; }
第三部,在前台界面中编写Ajax的核心技术支持——javascript代码
<script type="text/javascript" language="javascript">
//endRequest相应Request时最后触发的一个事件
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, e)
{
e.set_errorHandled(true);
//将信息显示到上面的div区块中innerHTML,这里可以设置默认的错误信息
$get("error").innerHTML = "Sorry, an error has occurred: " + e.get_error().message;
setTimeout(function(){ $get("error").innerHTML = ""; }, 3000);
});
</script>
技术学习:
endRequest相应Request时最后触发的一个事件;
通过Sys.WebForms.PageRequestManager.getInstance()方法获取控件的实例;
e参数封装相关的参数信息;
需要e.set_errorHandled()方法的意思是在客户端处理错误,需要设置成true;
$get("error").innerHTML方法向叶面中添加dom元素;
e.get_error().message方法来负责最终的错误信息的显示;
e.get_response().get_statusCode() != 200,遇到未知错误;
e.get_response().get_timedOut(),请求超时;
showMessage(e.get_error().message),显示错误处理信息;
e.get_response().get_aborted(),请求被取消;
var upId = "<%= this.UpdatePanel1.ClientID %>";
e.get_dataItems()[upId],注册updatepanel?
e.get_error()内封装了上面的e中的属性信息。
补充说明,前台界面中将一个命令按钮,添加到updatepanel控件中
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" /> </ContentTemplate> </asp:UpdatePanel>
经过以上步骤我们就可以在前台中单击命令按钮显示自定义的错误信息了,运行效果如下图:
个人见解:
以上方法通过是在客户端进行的错误提示,并没有与服务器端进行交互,我们可以在客户端向服务端进行数据提交的时候,进行数据验证,这样可以提高程序的效率,降低带宽的浪费。
2、服务器端定义的错误处理
Ajax最强悍的地方就是服务器和客户端之间的异步交互,如果客户端在于服务器交互的时候出现错误,一个不错的做法就是,服务器端封装一些自定义的错误处理,然后通过回调函数来与客户端进行交互。
因为在上一篇博客中已经对服务器和客户端之间的交互进行了简要的概述,这里就不再赘述。
1.在服务端ErrorHandling.asmx自定义除0和超时的错误函数
<%@ WebService Language="C#" Class="ErrorHandling" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.Web.Script.Services; using System.Threading; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] public class ErrorHandling : System.Web.Services.WebService { [WebMethod] //除0错误,注意,Ajax中额数值类型只有整型和浮点数之分,如果针对浮点数出现的除0,结果会是一个无限大或小的极值。 public int GetDivision(int a, int b) { return a / b; } [WebMethod] //自定义超时错误 public int Timeout() { Thread.Sleep(5000); return 0; } }
2.客户端页面中引用服务端错误处理的方法<asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="ErrorHandling.asmx" /> </Services> </asp:ScriptManager>
3.添加异步处理的javascript代码异步的意思就是调用的方法、接收的方法、处理的方法必须是不同的方法。
<script language="javascript" type="text/javascript"> function getDivision(a, b) { //除0错误 ErrorHandling.GetDivision(a, b, null, failedCallback); } function timeout() { //必须在客户端设置超时的时间 ErrorHandling.set_timeout(2000); //超时处理 ErrorHandling.Timeout(null, failedCallback); } //错误处理的回调函数 function failedCallback(error) { var message = String.format( "Timeout: {0}\nMessage: {1}\nExceptionType: {2}\nStackTrace: {3}", error.get_timedOut(), error.get_message(), error.get_exceptionType(), error.get_stackTrace()); alert(message); } </script>
技术学习:
这里的错误回调函数的error参数中封装了错误的类型、发生错误的堆栈、错误的具体信息等,为我们在调试程序的时候提供了重要的参考价值。
4.通过事件调用错误
<input type="button" value="getDivision" οnclick="getDivision(5, 0)" />
<input type="button" value="timeout" οnclick="timeout()" />
5.运行效果
个人见解:
程序中的错误处理是关系客户给公司的服务的很关键的评价,而且还是公司内部开发和维护人员跟踪程序的重要线索,做好错误处理,是一件利己又益人的事情,做好错误处理,彰显程序的魅力!
另外还有一个在服务端设置抛出错误的属性,而不是产生错误的代码,暂时想不起来了,希望路过的大牛、小牛们,多留言指点。
后记:
程序员是一个高尚的职业,空调咖啡不流汗的背后是我们幽静的思考,文章末尾附上一张意境优美的图片,献给那些正在为家室、为事业甚至为国家操劳的程序猿们……