ASP.NET 2.0 Ajax程序:处理异步调用中的异常


在传统的Web应用程序中,处理异常相对来说比较简单——即使开发者不作任何处理,浏览器也会默认地将收到的异常信息显示在浏览器中。而对于Ajax应用程序来说,事情却并不那么简单。Ajax程序“异步”的天性加上其后台运行的行为,让用户乃至开发者都很难判断某次对服务器的调用是否顺利完成,浏览器自然也对Ajax程序运行时发生的异常无能为力。
  在本章前面两节中,借助于 ASP.NET AJAX异步通信层的帮助,我们已经能够容易地从客户端向服务器端发起异步HTTP请求——在理想情况下,这自然不会有问题,也足够使用。然而,Web程序在运行中会有很多不确定性,从网络状况的不稳定到开发者的粗心大意,任何一个环节出了问题均会导致某次异步调用以失败告终。

  因此,在ASP.NET AJAX异步通信层的实现中,自然也内建了对异步调用时异常的处理方法
。还记得前面曾经介绍过的在客户端调用Web Service代理的语法吗?  [NameSpace].[ClassName].[MethodName](param1, param2,..., callbackFunction)

  在调用成功的回调函数callbackFunction的后面,我们还可以提供另一个调用失败的回调函数。这样,客户端调用Web Service代理的语法就变为:

  [NameSpace].[ClassName].[MethodName](param1, param2,..., onSucceeded, onFailed)

  注意其中粗体部分新添加的onFailed回调函数,该函数将在本次异步通信出现异常时由ASP.NET AJAX异步通信层调用。而onSucceeded的行为不会受到任何影响,仍将在成功调用后执行。

  onFailed回调函数将接受一个类型为Sys.Net.WebServiceError的参数,表示异常对象。其函数签名将类似如下所示:

  function onFailed(error) {
    // 取得异常信息并处理。
  }

  ASP.NET AJAX的客户端Sys.Net.WebServiceError类型封装了异步请求服务器时可能发生的异常,它提供了若干个只读的属性,提供了对异常信息的详细描述。Sys.Net.WebServ- iceError类型的属性如表3-1所示。

  表3-1 Sys.Net.WebServiceError类型的属性

  

  属  性

  描  述

  exceptionType

  获取服务器端异常的具体类型

  message

  获取详细的异常描述信息

  statusCode

  获取造成异常的HTTP响应的状态码

  stackTrace

  获取服务器端异常的栈跟踪信息

  timedOut

  获取一个布尔值,表示异常是否是由于网络连接超时造成的

  根据ASP.NET AJAX客户端组件的命名规范,访问属性均需要在属性名称前加上get_或set_前缀。例如,若想得到某个Sys.Net.WebServiceError类型异常的message属性值,则应该按照如下方式书写代码:

  var errorMessage = errorObj.get_message();

  下面让我们用一个简单的示例程序演示在客户端调用Web Service代理时发生异常的处理办法,以及Sys.Net.WebServiceError类型中各个属性的使用方法。

  该示例程序是一个除法计算器,程序将借助ASP.NET AJAX异步通信层将用户输入的除数和被除数发送至服务器,服务器完成具体的除法计算过程后再将结果返回至客户端显示出来。程序运行的初始界面如图3-4所示。

  

图3-4 除法计算器的初始界面

  输入除数和被除数,然后点击问号(?)按钮,程序将调用服务器端Web Service完成本次除法,并将商显示在问号按钮中,如图3-5所示。

  

图3-5 执行一次普通的除法

  若是用户输入的除数为0,那么服务器端执行时显然要抛出异常。我们没有在服务器端对该异常进行处理,因此将导致本次异步调用失败,客户端也会显示出异常的详细信息,如图3-6所示。

  

图3-6 除数为0导致本次除法失败

  让我们先从服务器端的Web Service入手。将该Web Service命名为MathService,并在其中定义了一个名为Divide()的方法,用来执行除法操作。Divide()方法所接受的两个参数分别代表被除数和除数,其逻辑非常简单,代码如下:

  [WebService(Namespace = "http://tempuri.org/")]
  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  [ScriptService]
  public class MathService : System.Web.Services.WebService
  {
    [WebMethod]
    public int Divide(int a, int b)
    {
      return (int)(a / b);
    }
  }

  这里有必要再次提醒一下,Web Service类要添加[ScriptService]属性,其中需要暴露给客户端的方法也要添加[WebMethod]属性——这些都是允许从客户端调用该Web Service代理的必要条件。

  在ASP.NET页面中,添加ScriptManager控件以及上述Web Service的引用:

  <asp:ScriptManager ID="sm" runat="server">
    <Services>
      <asp:ServiceReference Path="Services/MathService.asmx" />
    </Services>
  </asp:ScriptManager>

  然后在ASP.NET页面中定义程序的界面:

  <input id="tbA" type="text" style="width: 40px" /> /
  <input id="tbB" type="text" style="width: 40px" /> =
  <input id="btnInvoke" type="button" value="?"
    onclick="return btnInvoke_onclick()" />
  <div id="result"></div>

  其中前两个<input />(id分别为tbA和tbB)用来让用户输入被除数和除数;第三个<input />(id为btnInvoke)则作为按钮(type="button")用来触发对服务器端Web Service的调用,并显示除法完成后的商;下面id为result的<div />用来显示可能出现的异常信息。

  btnInvoke的click事件的处理函数为btnInvoke_onclick(),其代码如下:

  function btnInvoke_onclick() {
    var a = $get("tbA").value;
    var b = $get("tbB").value;
    MathService.Divide(a, b, onSucceeded, onFailed);
  }

  注意其中粗体部分,即调用Web Service客户端代理的一行。其中不但传入了被除数和除数(a和b),还传入了成功调用后的回调函数onSucceeded以及失败时的回调函数onFailed。

  成功调用时的回调函数onSucceeded()比较简单,这里不赘:

  function onSucceeded(result) {
    $get("btnInvoke").value = result;
   
    $get("result").innerHTML = "";
  }

  失败时的回调函数onFailed()才是本示例程序的重点:

  function onFailed(error) {    
    // 取得异常信息。
    var stackTrace = error.get_stackTrace();
    var message = error.get_message();
    var statusCode = error.get_statusCode();
    var exceptionType = error.get_exceptionType();
    var timeout = error.get_timedOut();
   
    // 显示异常信息。
    $get("result").innerHTML =
      "<strong>Stack Trace: </strong>" + stackTrace + "<br/>" +
      "<strong>Service Error: </strong>" + message + "<br/>" +
      "<strong>Status Code: </strong>" + statusCode + "<br/>" +
      "<strong>Exception Type: </strong>" + exceptionType + "<br/>" +
      "<strong>Is Timeout: </strong>" + timeout;
     
    $get("btnInvoke").value = "?";
  }

  可以看到,onFailed()函数首先取得了传递进来的Sys.Net.WebServiceError对象的各个属性,然后再依次显示到id为result的<div />中。

  这样就完成了本示例程序的编写。运行该程序并尝试做一些除法,若程序编写正确的话,你将看到如图3-4、图3-5和图3-6所示的界面。

  当然,本示例程序的目的是为了演示调用服务器端Web Service时发生异常的处理方法,所以自然事无巨细地将所有异常信息均显示了出来。而在实际开发中,我们则不应该完整显示出此类唐突的异常细节。通常的做法是根据不同的异常进行相应的处理,并在需要的情况下再为用户显示出相对友好的提示消息


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3