技术开发 频道

ASP.NET AJAX:当我们不需要state


【IT168专稿】

当我们不需要状态(state)


    当我们不要求我们的应用程序来保持状态时,我们可以使用基本的HTML 和 JavaScript,为我们的服务器上面的代码提供异步呼叫。不使用状态这一方法的好处就是它非常轻巧——我们不再要求服务器完全回传。

    ASP.NET AJAX通过使用JavaScript,为在服务器上面调用代码提供了一个丰富的结构。我们有能力异步地调用ASP.NET Web Service或者WCF Service方法,ASP.NET Web Service 或者 WCF Service方法都被安装在了服务器上面——所有的都没有围着服务器转。

    在看任何代码之前,首先看一下怎样在Web Service上访问方法。在这篇文章前面(使用了状态的部分)已经知道ScriptManager控件有多重要,因为它能定义一个ScriptManager控件的Services子元素,以及给服务器上的服务增添一个引用,所以它变得更好。在代码1中,我们为People Web Service补充了一个引用,此People Web Service是一个ASP.NET Web Service.

代码1: 参考一个Web Service

<asp:ScriptManager 
ID="sm"
runat="server">
<Services>
<asp:ServiceReference
Path="~/WebServices/PeopleWebService.asmx" />
</Services>
</asp:ScriptManager>
    当运行这个代码时将看到引用了URL,此URL和Web Service有同样的地址,然而,它上面附加有一个标记。JavaScript文件是一个自动生成的代理,为了从客户上的JavaScript代码中调用Web Services方法。我们不能在Web Services中使用这个功能,我们必须明确地定义:通过使用ScriptService属性(在System.Web.Scripts.Services命名空间里可以找到,)我们的Web Service可以被客户JavaScript调用,代码2显示了这些。

代码2: 允许一个Web Services的方法被client JavaScript调用
[ScriptService] 
public class PeopleWebService : System.Web.Services.WebService {
// ....
}



    现在建立了Web Service and ScriptManager,接着再创建某些JavaScript代码,此代码将简单地从服务器上面重新找到当前的数据和时间。(如代码3)

代码3: 异步调用一个Web Service中的一个method
Collapse 
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ServerTime.aspx.cs"
Inherits="No_State_ServerTime" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Server Time</title>
<script type="text/javascript">
function GetServerTime() {
PeopleWebService.GetServerTime(OnSuccessCallback, OnServiceTimeout,
OnServiceError);
}

function OnSuccessCallback(result) {
alert(result);
}

function OnServiceTimeout(result) {
alert(result);
}

function OnServiceError(result) {
alert(result);
}
</script>
</head>
<body>
<form id="form1" runat="server">

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

<input
type="button"
value="Get Server Time"
onclick="GetServerTime()" />

</form>
</body>
</html>
     在代码3中,当点击输入按钮时,我们调用了一个被称为GetServerTime() 的功能,在这个功能中,我们调用了方法GetServerTime ,此方法GetServerTime 被定义在PeopleWebService.asmx 文件中。我们访问了JavaScript 服务中的方法,好像这些服务是静态定义的类型一样(例如WebServiceName.NameOfMethod)。当我们从服务返回某些数据时要调用的功能,当服务超时或者出错时我们该怎么办?OnSuccessCallback功能产生了参数结果,结果就是返回的任何数据类型的变量名称——它可能是一个 阵列,整数,或者其它……在这种情况下,我们返回了一个字符串——然后我们将那个字符串显示在一个示警框中(如代码3所示).



图1: 调用一个Web Service中一个method的结果


    现在已经讨论了Web Service的方法是怎样被调用的,下面要讨论的就是:什么样的数据通过网线被发送到客户,更重要的是,是怎样被发送的客户的。当调用Web Service方法时,我们使用JavaScript Object Notation (JSON)将数据返回到客户。为什么使用JSON的原因很简单,它比发送被串行化的XML更加容易,不像XML那样需要从语法上分析——可以自然地执行JSON(只有调用代码是安全的,我们不需要把令人厌烦的脚本通过网络发送给我们的用户)。图10中,当调用了图7中的OnSuccessCallback时,我们检查了被发送给客户的数据。意需要注意的是:在下面的例子中,我们将看一些更复杂的、在网络上传输的数据。 

图2: 看看在使用JSON时通过网络发送了什么



    此刻,通过使用JSON,我们只给客户发送了一些简单的字符串数据类型,现在给客户发送一个定制的类型。当给客户返回复杂的、定制的类型时,需要要让系统知道:我们打算向客户发送什么样的类型,因此我们要为Web Service增添另一个属性——GenerateScriptType(typeof(MyType)),这个属性位于System.Web.Script.Services命名空间。在进一步操作之前,我们先应该看一下Person Web Service代码后置的档案(代码4)。

代码4: PersonWebService.asmx后面的代码
Collapse
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Web;
using System.Web.Configuration;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://gbarnett.org/services")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
[GenerateScriptType(typeof(Person))]
public class PeopleWebService : System.Web.Services.WebService {

public static string _conn
= WebConfigurationManager.ConnectionStrings["CodeProjectConn"]
.ConnectionString;

public PeopleWebService() { }

[WebMethod(Description="Gets a list of all the People")]
public Person[] GetPeople() {
List personList = new List();
using (SqlConnection sqlConn = new SqlConnection(_conn))
using (SqlCommand sqlCmd
= new SqlCommand("SELECT PersonId, FirstName, LastName FROM People",
sqlConn)) {
sqlConn.Open();
SqlDataReader sqlRdr = sqlCmd.ExecuteReader();
while (sqlRdr.Read()) {
personList.Add(new Person((int)sqlRdr.GetInt32(0),
sqlRdr.GetString(1) as string,
sqlRdr.GetString(2) as string));
}
}
return personList.ToArray();
}

[WebMethod(Description = "Returns the time on the server")]
public string GetServerTime() {
return DateTime.Now.ToLongDateString() + ", " +
DateTime.Now.ToLongTimeString();
}

}

代码5: Person type的定义
using System; 

/// <SUMMARY>
/// Person entity
/// </SUMMARY>public class Person {

private int _personId;
private string _firstName;
private string _lastName;

public Person() { }

public Person(int personId, string firstName, string lastName) {
_personId = personId;
_firstName = firstName;
_lastName = lastName;
}

public int PersonId {
get { return _personId; }
}

public string FirstName {
get { return _firstName; }
set { _firstName = value; }
}

public string LastName {
get { return _lastName; }
set { _lastName = value; }
}

}
    我们对GetPeople方法感兴趣,GetPeople方法返回一堆类型Person(Person类型代码显示在代码6中)。对于下面一个例子将调用GetPeople这个方法,然后重新叙述项目,输出一个HTML无序表(如代码6)。

Collapse 
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PeopleList.aspx.cs"
Inherits="NoStateViewPeople" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">

<title>Untitled Page</title>

<script type="text/javascript">
function GetPeople() {
PeopleWebService.GetPeople(OnCompleteCallback, OnServiceTimeout,
OnServiceError);
}

function OnCompleteCallback(result) {
for(i = 0; i < result.length; i++) {
$get("people").innerHTML += "<li>" + result[i].LastName + ", " +
result[i].FirstName + "</li>";
}
}

function OnServiceTimeout(result) {
alert(result);
}

function OnServiceError(result) {
alert(result);
}
</script>

</head>
<body>

<form id="form1" runat="server">

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

<input
type="button"
value="Get People"
onclick="GetPeople()" />

<ul
id="people"></ul>

</form>
</body>
</html>

    因为调用GetPeople()方法的结果会返回一个阵列,结果变量的类型就是类型Person 阵列。有意义的是:我们可以使用C#代码(例如:result[i].FirstName)访问Person类型的属性。

    总结不使用state的情况,当调用People Web Service 的GetPeople()方法时,可以看一下JSON 对象图 (如代码7)的形式。

    图3: JSON 对象图


总结

    通过这篇文章可以看到了ASP.NET AJAX的能力和灵活性。我们研究了当使用ASP.NET AJAX结构时,使用state和没有使用state这两种方法的优点和缺点,我们也检查了每一个方法中通过网络发送的数据。
0
相关文章