asp.net中的AJAX编程-异步网络调用

    Ajax编程的核心就是能够从浏览器向服务器建立异步调用。通过建立这种会话,无需因每一次请求或用户交互而要求浏览重新加载。它可以在后台交换数据,浏览器以页面进行浙进式更新。利用客户端中心的开发模型,可以将逻辑从服务器转移至服务器,从而对应用程序有更多的控制。以这种方式,意味着服务器主要用于提供数据,而不提供应用逻辑。
    一般来说,可以在服务器配置相应的WEB服务,而客户端利用Javascript异步调用服务器端的WEB服务。调用的过程都是可以通过异步的方式获取。

1.建立WEB服务

   建立WEB服务可以参考《OReilly.Programming.ASP.NET.3rd.Edition》中的第15章,一个简单的WEB服务示例如下所示:

Stock.WebService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;   //引入脚本服务的命名空间

// 建立Stock类
public class Stock
{
    
public Stock(){}
    
public Stock(string stockSymbol,String stockName,double stockPrice)
    {
        _stockSymbol 
= stockSymbol;
        _stockName 
= stockName;
        _stockPrice 
= stockPrice;
    }

    
private string _stockSymbol;
    
private string _stockName;
    
private double _stockPrice;

    
public string StockSymbol{
        
get { return _stockSymbol; }
        
set { _stockSymbol = value; }
    }

    
public string StockName {
        
get { return _stockName; }
        
set { _stockName = value; }
    }

    
public double stockPrice {
        
get { return _stockPrice; }
        
set { _stockPrice = value; }
    }
}

[WebService(Name
="StockTickersWebServer",Namespace = "http://Dawnsoft.com/",Description="通过股票代码获得股票的相应信息")]
[WebServiceBinding(ConformsTo 
= WsiProfiles.BasicProfile1_1)]
//若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
[System.Web.Script.Services.ScriptService]   // 支持AJAX服务
public class StockTickerSimple : System.Web.Services.WebService
{
    
protected string[,] stocks =
    {
        {
"MSFT","Microsoft","25.30"},
        {
"DELL","Dell Computers","34.83"},
        {
"HPQ","Hewlett Packard","20.47"},
        {
"YHOO","Yahoo!","34.50"},
        {
"GE","General Electric","36.20"},
        {
"IBM","International Business Machine","76.38"},
        {
"GM","General Motors","26.68"},
        {
"F","Ford Motor Company","9.11"}
    };

    
public StockTickerSimple()
    {

        
//如果使用设计的组件,请取消注释以下行
        
//InitializeComponent();
    }

    [WebMethod(CacheDuration
=1800,Description="返回股票的价格")]
    
public double GetPrice(string StockSymbol)   // 向外界暴露GetPrice方法
    {
        
for(int i=0;i<stocks.GetLength(0);i++)
        {
            
if(string.Compare(StockSymbol,stocks[i,0],true)==0)
                
return Convert.ToDouble(stocks[i,2]);
        }
        
return 0;
    }

    [WebMethod]
    
public string GetName(string StockSymbol)  // 向外界暴露GetName方法
    {
        
for (int i = 0; i < stocks.GetLength(0); i++)
        {
            
if(string.Compare(StockSymbol,stocks[i,0],true)==0)
                
return stocks[i,1];
        }
        
return "Symbol not found";
    }

    [WebMethod]
    
public Stock GetStockObject(string stockSymbol)  // 向外界暴露获得Stock对象的方法
    {
        
for (int i = 0; i < stocks.GetLength(0); i++)
       {
            
if (string.Compare(stockSymbol, stocks[i, 0], true== 0)
            {
                Stock stock 
= new Stock(stockSymbol, stocks[i, 1], Convert.ToDouble(stocks[i, 2]));
                
return stock;
            }
       }
        
return null;
    }


    以上,一个WEB服务就建立了,你可以通过相应的URL查看WEB服务,如:http://localhost/DawnEnterprise/webServices/StockTickerSimple.asmx
    并且通过http://localhost/DawnEnterprise/webServices/StockTickerSimple.asmx/js 链接可以看到一组Javascript函数,利用这些函数可以从脚本调用WEB方法,这些Javascript代码被称为代理(proxy)或称为WEB服务代理。
    下面就是在页面上增加一个与WEB服务交互的页面

2. Javascript中调用WEB服务方法和页面上的方法

    在Javascript中调用WEB服务方法有以下几点需要注意。
    2.1 ScriptManager的WEB服务支持
       第一步肯定是增加Ajax支持,增加Ajax支持的方法是加入ScriptManager控件。第二步是在ScriptManager控件中添加一个服务引用,如下所示:

< asp:ScriptManager  ID ="ScriptManager1"  runat ="server" >
< Services >
    
< asp:ServiceReference  Path ="~/webServices/StockTickerSimple.asmx"  InlineScript ="true"   />
</ Services >
</ asp:ScriptManager >

      以上,ScriptManager控件的Service属性包含一个ServiceReference对象集合。一个ServiceReference对象就是一个本地WEB服务的引用。
      ServiceReference的InlineScript属性设置为true说明Web服务代理程序会随页面下载,false则将代理程序单独下载到浏览器。
相关的Javascript代理程序如下图所示:
asp.net中的AJAX编程-异步网络调用_第1张图片


    2.2 调用WEB服务
      第二步肯定是要调用WEB服务,需要告知页面,是在什么场合下调用WEB服务呢,发生PageLoad事件,发生Button的Click事件..都可以作为调用WEB服务的场合。
      以下所示的就是在点击Button后调用相应的WEB服务.

Ajax.CallWebService
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
     
<asp:ServiceReference Path="~/webServices/StockTickerSimple.asmx" InlineScript="true" />
</Services>
</asp:ScriptManager>
<script type="text/javascript" language="javascript">
     
var ticketName = "";
     
var ticketPrice = "";
     
function getTicketNameAndPrice() {
         
var ticketSymbol = $get("txtTicketSymbol").value;
         StockTickerSimple.GetName(ticketSymbol, onGetNameSuccess, onGetNameFailure, 
"<%=DateTime.Now%>");
         StockTickerSimple.GetPrice(ticketSymbol, onGetPriceSuccess, onGetPriceFailure, 
"<%=DateTime.Now%>");
         
// 以上,第一个参数表示的是WebSerivce方法的参数,第二个参数表示的是成功返回时调用的函数,
         // 第三个参数(可选)表示的是失败返回时调用的函数,第四个参数(可选)表示的是传入用户的上下文。
         // 在两个回调函数中,都可以使用这个上下文,上下文可以是任何Javscript类型。
     }

     
/* 以上四个都是回调方法 */
     
function onGetNameSuccess(result, context, methodName) {
         ticketName 
= "Name:" + result;
         
if (ticketPrice != "")
             $get(
"TickNameAndPrice").innerHTML = ticketName + "  " + ticketPrice;
     }

     
function onGetNameFailure(result, context, methodName) {
         
var errorMessage = error.get_message();
         $get(
"TickNameAndPrice").innerHTML = errorMessage;
     }

     
function onGetPriceSuccess(result, context, methodName) {
         ticketPrice 
= "Price:" + result;
         
if(ticketName!="")
             $get(
"TickNameAndPrice").innerHTML = ticketName + "  " + ticketPrice;
     }

     
function onGetPriceFailure(result, context, methodName) {
         
var errorMessage = error.get_message();
         $get(
"TickNameAndPrice").innerHTML = errorMessage;
     }
</script>
     
<input id="txtTicketSymbol" type="text" />&nbsp;
     
<input id="Button1" type="button" value="button" onclick="getTicketNameAndPrice()" /></div>
     
<div id="TickNameAndPrice"></div>
</form> 


     以上,从Javascript调用WEB服务时,成功或失败回在相应的回调函数中反映出来,但是,在异步的请况下,有时必须考虑处理一个请求所花费的时间。在某些情况下,可能希望调用立即返回,所以需要设置一个较短的时间值,在另外的情况下,可能需要设置较长时间,从而保证服务器有足够的时间来处理请求。所以,ASP.NET中客户端代理公布了一个timeout属性,可以利用这个属性调用超时间隔。
     StockTickerSimple.set_timeout(1000); // 设置超时为1秒
    如果超过时限,但还未收到响应,就会在客户端产生一个异常,并调用失败回调函数。

    2.3 处理复杂类型
       在前一节中,我们调用相关的WEB服务中的共开方法,这些方法返回的一个是字符串格式,一个是数值格式,但是,如果方法返回的是一个对象怎么办?在JS中怎么处理这个对象。
       在我们编写的WEB服务中,有一个GetStockObject方法,它返回的是一个Stock类型,下面就是在JS中怎么利用这些对象的代码:

Ajax.CallWebService.ComplexObject
<script type="text/javascript" language="javascript">
function getTicketObject() {
    
var ticketSymbol = $get("txtTicketSymbol").value;
    StockTickerSimple.GetStockObject(ticketSymbol, onGetObjectSuccess, onGetObjectFailure);
}

function onGetObjectSuccess(result, context, methodName) {
    
var ticketObject = result;
    
if (ticketObject)
          $get(
"TickNameAndPrice").innerHTML = ticketObject.StockName + "  " + ticketObject.stockPrice;
    
else
          $get(
"TickNameAndPrice").innerHTML = "There is no result in the Tickets";
}
function onGetObjectFailure(result, context, methodName) {
     
var errorMessage = error.get_message();
     $get(
"TickNameAndPrice").innerHTML = errorMessage;
}

<input id="txtTicketSymbol" type="text" />&nbsp;
<input id="Button2" title="" type="button" value="GetTickObject" onclick="getTicketObject()" /></div>
<div id="TickNameAndPrice"></div> 

     以下的例子是在JS中处理返回数组类型的代码:

Ajax.CallWebService.MutliObject
<div>
    
<input id="GetDeals" type="button" value="Get Deals" onclick="getDeals()" />
    
<div id="Deals"></div>
</div>

function getDeals(){
    AspNetAjaxInAction.StarbucksService.GetDeals(onGetDealsSuccess,
    onGetDealsFailure);
}
function onGetDealsSuccess(result, context, methodName){   
    // result由WEB服务的方法返回一个List
<Beverage>对象,在JS中直接当作数组处理
    var sb = new Sys.StringBuilder(); 
    for (var i = 0; i 
< result.length; i++){
    var bev 
= result[i];
    
sb.append(bev.Name + " – ");
   sb.append(bev.Description + " – ");
   sb.append(bev.Cost + "<br 
/>");


    2.4 在客户端创建服务器类型
       在上一节,可以知道在客户端可以处理服务器中创建的类型,但是,有没有一种办法,可以在客户端实例化服务器端类的实例?
       其中,如果类在WEB服务的文件中定义,完全可以直接定义相关的类,如以上的Stock类,可以在客户端这样定义:

var stockObject  =   new  AspNetAjaxInAction.Stock();
stockObject.StockSymbol 
=   " HAI " ;
stockObject.StockName 
= " Haier " ;
stockObject.StockPrice 
=   21.12 ;

       定义好后,就可以作为对象传递给WEB服务的某个方法,在WEB服务中,完全有能力识别这个对象。
       另外,如果定义的类不在WEB服务文件中呢,比如,定义在一个cs类文件中,这时候怎么使用这个类来实例化对象?这时候可以在WEB服务的文件(asmx)中告诉WEB服务把这个类包含在代理中。可以使用GenerateScriptType标签,并提供想要包含的类类型,这样子的话,这个类型也将在WEB服务代理中得到支持,如下所示:

WebService.GenerateScriptType
[ScriptService]
[GenerateScriptType(
typeof(Employee))]   // 引入外部类定义
[WebService(Namespace = "http://aspnetajaxinaction.com/")]
[WebServiceBinding(ConformsTo 
= WsiProfiles.BasicProfile1_1)]  
public class StarbucksService : System.Web.Services.WebService
{
      
// WebService Class Define 
}


      相应的,在客户端可以直接定义和使用Employee类型:

function  createEmployee(){
    
var  emp1  =   new  AspNetAjaxInAction.Employee();
    emp1.First 
=   " Frank " ;
    emp1.Last 
=   " Rizzo " ;
    emp1.Title 
=   " Principal " ;
}

   
     2.5 使用HTTP GET
        在以上的异步调用中,对WEB服务所做的调用使用的都是HTTP POST方式,ASP.NET默认的从浏览器只接受这种类型的请求,要处理一个HTTP GET请求,必须显式的用ScriptMethod属性装饰一个方法,并设置UseHttpGet为True,那么调用这个方法的时候,将会使用HTTP GET方式

[ScriptMethod(UseHttpGet = true )]    //  可以使用HTTP GET方式
[WebMethod]
public List
< Beverage >  GetDeals()
{
     
//  WebService Method Define
}

 

     2.6 调用页面方法
          在以上所有的AJAX异步调用中,调用的方法都是WEB服务中的方法。AJAX还支持Javascript调用ASP.NET页面本身声明的方法。 这些方法在页上声明(即在aspx.cs)中声明,而不是在WEB服务中声明,所以被称为页面方法。调用页面方法的代码如下:

aspx.WebMethod.Prototype
[WebMethod]    // 页面的方法中必须要有WebMethod特性修饰
public static string HelloEmployee(AspNetAjaxInAction.Employee emp)  // 一般来说,也都是声明静态方法
{
    
return string.Format("Hello {0} {1}.", emp.First, emp.Last);

         在页面Javascript代码中,ScriptManager的EnablePageMethods属性设置为true,就可以支持页面方法了。

Ajax.ScriptManager.EnablePageMethod
<asp:ScriptManager ID="ScriptManager1" runat="server"
    EnablePageMethods
="True">
<Services>
    
<asp:ServiceReference Path="StarbucksService.asmx" InlineScript="true" />
</Services>
</asp:ScriptManager>

你可能感兴趣的:(asp.net中的AJAX编程-异步网络调用)