ASP.NET Spiced:AJAX

 

卡尔·塞金

2005 年 9 月

适用于:
   AJAX (异步 JavaScript 和 XML)
   Microsoft AJAX.NET
   Microsoft ASP.NET

总结: 了解如何使用 AJAX (异步 JavaScript 和 XML) 使 Microsoft ASP.NET 应用程序更具动态性和响应能力。 (17 个打印页)

下载本文的代码示例, AjaxASPNETCS.msi C#

下载本文的代码示例, 在 Visual Basic 中AjaxASPNETVB.msi

目录

简介
什么是 AJAX?
AJAX for ASP.NET
AJAX Hands-On
AJAX 和 You
结论

简介

自 Web 编程开始以来,Web 应用程序和桌面应用程序之间存在许多权衡。 例如,人们普遍认为,Web 应用程序不提供与桌面应用程序相同类型的丰富用户界面。 另一方面,Web 应用程序独立于平台,并提供更简单的开发机制。 对于 Web 开发人员来说,一个持续战场的一个领域是提供响应性更高的应用程序这一看似简单的任务。

传统上,只能通过向 Web 服务器提交新请求来检索对用户输入的响应。 在某些情况下,开发人员可以使用 JavaScript) 加载客户端 (上的所有响应,并提供更好的用户体验。 此方法的一个常见示例是基于所选国家/地区动态加载州或省的列表。 遗憾的是,在许多情况下,无论是回发还是将所有内容加载到 JavaScript 中,都感觉不正确。 回发过多的 UI 断开连接,或者在客户端 (上需要不可管理的数据量,这通常会导致 JavaScript) 不可读。 AJAX 提供了一种新的中间替代方案,能够利用基于服务器的应用程序,同时保持响应和流畅的感觉。

什么是 AJAX?

AJAX 是异步 JavaScript 和 XML 的缩写,它不是一种技术,而是一组技术。 AJAX 使用通信技术 (通常为 SOAP 和 XML) 来发送和接收对服务器的异步请求/响应,然后利用 JavaScript、DOM、HTML 和 CSS) (表示技术来处理响应。 使用 AJAX 的应用程序目前是合法的,因为大多数浏览器都支持必要的技术。 有关 AJAX 的更详细定义,请访问 AJAX 维基百科条目

AJAX 的真正含义是什么? 它允许通过 JavaScript 调用执行服务器端方法,而无需刷新浏览器。 将其视为在用户后台发生的小型请求/响应。 如果仍然不清楚 AJAX 是什么,请查看 Google 的两个热门示例: Google SuggestsGoogle Maps。 如果你不熟悉 AJAX,那么这两个应用程序的响应能力应该会让你的皮肤略有毛皮。

AJAX for ASP.NET

大量的管道进入使 AJAX 滴答作响。 你可能不想花费数小时或数天来弄清楚 AJAX 的内部信息,而是希望立即开始创建已启用 AJAX 的应用程序,以满足现有需求 (,如果你确实想要了解它的内部工作原理,我肯定不是要求) 的人。 开发人员可以使用多种工具快速入门。 具体来说,我们将介绍迈克尔·施瓦茨撰写的免费开源 Ajax.NET。 Ajax.NET 负责所有实现详细信息, 是 。可识别 NET,可以扩展。 Microsoft ASP.NET 2.0 通过 客户端回调功能引入了自己的异步回调风格, 最近宣布 ,一个代号为“Atlas”的 AJAX 实现正在实施中。

术语可能令人困惑,但当我谈论 AJAX 时,我将讨论用于从客户端异步调用服务器端函数的整体框架。 提及 Ajax.NET 时,我指的是一个特定实现,该实现可帮助你生成利用 AJAX 框架的解决方案。

若要详细了解 ASP.NET 2.0 的客户端回调功能,请务必访问 Bertrand Le Roy 的博客

AJAX Hands-On

本文的其余部分主要介绍三个有意义的示例,这些示例使用 Ajax.NET 利用 AJAX 的强大功能。 本指南将包含 Microsoft C# 和 Microsoft Visual Basic .NET 中的代码,有时两者都会提供,有时只提供其中一个或另一个。 实现所有这些操作的代码非常简单,C# 开发人员应该能够轻松地遵循 Visual Basic 。仅 NET 代码,反之亦然! 本文包含示例 C# 和 Visual Basic .NET 项目供下载,并提供工作和正在运行的代码。 在了解示例之前,需要一个关于设置和使用 Ajax.NET 的入门。

Ajax.NET

AJAX.NET 文档网站 在让开发人员启动和运行上做得非常好。 在查看此技术的一些具体示例之前,我们将简要介绍你需要了解的核心步骤。

首先,从 AJAX.NET 项目网站下载和解压缩 AJAX 文件,在 Visual Basic .NET 或 C# 中创建一个新的 ASP.NET 项目 (,无论你喜欢) ,并添加对 AJAX.dll 文件的 引用 。 唯一的配置步骤是,在 system.web> 元素内的<web.config 文件中添加以下代码。

<configuration>    
 <system.web>  
  <httpHandlers>
   <!-- Register the ajax handler -->
   <add verb="POST,GET" path="ajax/*.ashx" 
        type="Ajax.PageHandlerFactory, Ajax" />
  </httpHandlers>  
  ...
  ... 
 </system.web>
</configuration>

若要通过 JavaScript 使用服务器端函数,必须执行两项操作。 首先,必须用 Ajax.AjaxMethodAttribute 标记有问题的函数。 其次,必须通过调用 Ajax 注册包含这些函数的类 。在页面加载事件期间实用工具.RegisterTypeForAjax 。 如果听起来很复杂,别担心;实际上,代码中只有两个额外的行。 接下来举例说明。
C#

public class Sample : System.Web.UI.Page
{
 private void Page_Load(object sender, System.EventArgs e)
 {
  //Register the class containing the server-side function
  //we are interested in
  Ajax.Utility.RegisterTypeForAjax(typeof(Sample));
 }
 [Ajax.AjaxMethod()]
 public string GetMessageOfTheDay()
 {
  return "Experience is the mother of wisdom";
 }
}
'VB.NET
Public Class Sample
 Inherits System.Web.UI.Page

 Private Sub Page_Load(sender AsObject, e As EventArgs) 
                                         Handles MyBase.Load
  'Register the class containing the server-side function
  'we are interested in
  Ajax.Utility.RegisterTypeForAjax(GetType(Sample))
 End Sub
 <Ajax.AjaxMethod()> _
 Public Function GetMessageOfTheDay() As String
  Return "Experience is the mother of wisdom"
 End Function
End Class

上面的示例首先告知 Ajax.NET 查看 Ajax 友好方法的 Sample 类。 这恰好是与实际页面相同的类,但它可以是任何 .NET 类,也可以注册多个类。 然后,Ajax.NET 将查看特定类,查找使用 AjaxMethodAttribute 标记的任何方法,其中 Sample 类具有一个 GetMessageOfTheDay

完成此操作后,唯一要做的就是在 JavaScript 中使用它。 Ajax.NET 自动创建一个名为 的 JavaScript 变量,该变量与本示例中注册的类 (相同,它将是 示例) ,它公开的函数与本示例中的 AjaxMethod (相同,GetMessageOfTheDay) 。 这是它的外观。

<script language="javascript">
 Sample.GetMessageOfTheDay(GetMessageOfTheDay_CallBack);
 function GetMessageOfTheDay_CallBack(response)
 {
  alert(response.value);
 }
</script>

在这种情况下,JavaScript GetMessageOfTheDay 需要与其服务器端对应 (相同的参数,除了 JavaScript 回调函数之外,没有任何) 执行并在完成后将响应传递给 。 在这里,我们可以看到 AJAX 在工作时的异步性质,因为对 GetMessageOfTheDay 的 调用不会阻止其他 JavaScript 代码的执行,也不会阻止用户继续在页面上工作。 完成服务器端处理后,Ajax.NET 调用指定的回调函数 ,GetMessageOfTheDay_CallBack,并传递包含服务器端返回值的响应。

服务器端代码和 JavaScript 代码之间的映射可能会令人困惑。 图 1 显示了服务器端代码和 JavaScript 代码的大纲,以及两者之间的映射。

Aa479042.ajaxspiced_fig01 (en-us,MSDN.10) .gif

图 1. 服务器端代码与 JavaScript 代码之间的映射

当然,还有更多值得关注的 Ajax.NET,例如对 .NET 类型的支持和回调响应的丰富性, (它不仅仅是一个值) 。 以下示例希望重点介绍一些功能,并帮助你设想 AJAX 如何帮助你创建成功的应用程序。

示例 1:链接Drop-Down列表

本文开头简要讨论了用于将一个 DropDownList 链接到另一个 DropDownList 的两种传统方法。 当所选索引发生更改时,页面会重新发布,或者所有可能的数据都加载到 JavaScript 数组中并动态显示。 希望你能够了解如何将 AJAX 用作这两种解决方案的替代方法。

首先,让我们看一下数据接口,并从那里驱动示例。 我们的数据访问层将公开两种方法:第一种方法将检索系统支持的国家/地区列表,第二种方法将获取国家/地区 ID 并返回州/省列表。 由于这是纯数据访问,因此我们将仅查看方法签名。

//C#
public static DataTable GetShippingCountries();
public static DataView GetCountryStates(int countryId);
'VB.NET
Public Shared Function GetShippingCountries() As DataTable
Public Shared Function GetCountryStates(ByVal countryId As Integer)
                                                        As DataView

现在,让我们翻转到相反的层并创建简单的 Web 窗体。

<asp:DropDownList ID="countries" Runat="server" /> 
<asp:DropDownList ID="states" Runat="server" />
<asp:Button ID="submit" Runat="server" Text="Submit" />

Page_Load 事件同样简单,并且与前面的 Web 窗体一样常见。 我们使用数据访问层检索可用的国家/地区,并将其绑定到我们的 国家/地区DropDownList

//C#
if (!Page.IsPostBack)
{
 countries.DataSource = DAL.GetShippingCountries();
 countries.DataTextField = "Country";
 countries.DataValueField = "Id";
 countries.DataBind();
 countries.Items.Insert(0, new ListItem("Please Select", "0"));
}

这就是我们的代码不再成为典型代码的位置。 首先,我们将创建要从 JavaScript 调用的服务器端函数。

'VB.NET
<Ajax.AjaxMethod()> _
Public Function GetStates (ByVal countryId As Integer) As DataView
 Return DAL.GetCountryStates(countryId)
End Function

这与你通常拥有的任何其他函数类似:它需要我们想要获取的国家/地区的 ID,并将请求传递给 DAL。 唯一的区别是,我们已使用 AjaxMethodAttribute 标记方法。 最后一个服务器端步骤是注册包含上述方法的类 (在本例中,通过调用 RegisterTypeForAjax,使用 Ajax.NET 代码隐藏) 。

//C#
Ajax.Utility.RegisterTypeForAjax(typeof(Sample));
'VB.NET
Ajax.Utility.RegisterTypeForAjax(GetType(Sample))

我们快完成了:剩下的就是从 JavaScript 调用 GetStates 方法并处理响应。 从逻辑上讲,当用户从国家/地区列表中选择新项目时,我们希望调用 GetStates 。 为此,我们将挂钩到 JavaScript onChange 事件。 因此,我们的 Web 表单代码略有变化。

<asp:DropDownList onChange="LoadStates(this)" 
                  ID="countries" Runat="server" />

JavaScript LoadStates 函数将负责通过 Ajax.NET 创建的代理发出异步请求。 请记住,默认情况下,Ajax.NET 创建的代理的格式 <为 RegisteredTypeName>。<ServerSideMethodName>。 在本例中,该示例为 Sample.GetStates。 我们还希望在服务器端函数完成后传入国家/地区 ID 参数和 Ajax.NET 应调用的回调函数。

//JavaScript
function LoadStates(countries)
{
 var countryId = countries.options[countries.selectedIndex].value;
 Sample.GetStates(countryId, LoadStates_CallBack);
}

最后,最后一步是在 LoadStates_CallBack 函数中处理响应。 Ajax.NET 最高效的功能可能是它支持许多 .NET 类型 (我已经) 多次提到过此功能。 回想一下,我们的服务器端函数返回了 DataView。 JavaScript 对 DataView 的了解是什么? 没有,但 JavaScript 是一种面向对象的语言,Ajax.NET 不仅负责创建类似于 .NET DataView 的对象,而且还负责将函数中的返回值映射到 JavaScript 克隆。 应记住,JavaScript DataView 只是实际 DataView 的副本 (replica) ,目前 () 支持的功能比遍历行和访问列值 (功能(如设置 RowFilter 或 Sort 属性) )要多得多。

function LoadStates_CallBack(response)
{
 //if the server-side code threw an exception
 if (response.error != null)
 {
  //we should probably do better than this
  alert(response.error); 
  return;
 }

 var states = response.value;  
 //if the response wasn't what we expected  
 if (states == null || typeof(states) != "object")
 {
  return;
 }
 //Get the states drop down
 var statesList = document.getElementById("states");
 statesList.options.length = 0; //reset the states dropdown

 //Remember, its length not Length in JavaScript
 for (var i = 0; i < states.length; ++i)
 {
  //the columns of our rows are exposed like named properties
  statesList.options[statesList.options.length] = 
         new Option(states[i].State, states[i].Id);
 }
}

经过一些错误检查后,前面的 JavaScript 将获取状态下拉列表,循环访问响应的值,并将选项动态添加到下拉列表。 代码简洁明了,非常类似于 C# 和 Visual Basic .NET。 就个人而言,作为一名基于服务器端变量创建 JavaScript 数组并将其链接在一起的开发人员,我仍然很难相信它确实有效。

有一个主要问题可能并不明显。 由于 DropDownList 是在 JavaScript 中动态创建的,因此其项不是 ViewState 的一部分,因此不会进行维护。 这意味着按钮的 OnClick 事件处理程序需要执行一些额外的工作。

'VB.NET
Private Sub submit_Click(sender As Object, e As EventArgs)
  Dim selectedStateId As String = Request.Form(states.UniqueID)

  'should do some user validation...
  states.DataSource = 
     DAL.GetCountryStates(Convert.ToInt32(countries.SelectedIndex))
  states.DataTextField = "State"
  states.DataValueField = "Id"
  states.DataBind()
  states.SelectedIndex = 
    states.Items.IndexOf(states.Items.FindByValue(selectedStateId))
End Sub

首先,不能使用 状态。SelectedValue 属性,必须使用 Request.Form。 其次,如果要向用户重新显示列表,则需要绑定状态 DropDownList,值得庆幸的是,重用相同的数据访问方法。 最后,必须以编程方式设置所选值。

示例 2:文档保险箱

对于下一个示例,我们将采用更完整的功能,并使用 AJAX 对其进行改进。 此示例将是一个简单的文档管理系统。 与任何像样的文档管理系统一样,我们必须提供并发管理。 也就是说,我们需要一种处理两个尝试编辑同一文档的用户的方法。 为此,我们将创建某种类型的锁定机制,防止一个用户编辑已编辑的文档。 我们将使用 AJAX 使用户使用锁定机制的体验更加愉快。 首先,我们将创建一个用户尝试编辑但无法 (的文档队列,因为文档已在) 编辑,并在他们可用时自动通知他/她。 其次,如果用户关闭其浏览器或导航离开,我们将确保解锁文档。 最后一项功能有助于确保文档不会永久锁定。 在本指南中,我们将跳过与 AJAX 实现不专门相关的功能;但是,可下载的项目包含所有内容。

首先,当用户尝试编辑文档时,我们将尝试获取该文档的排他锁,否则,我们会将该文档添加到用户的队列中,并将他或她发送回main页。 此处没有特定于 AJAX 的内容,但我们将查看代码,以便为示例提供必要的上下文。 在用于编辑的 PageOnLoad 事件中,添加了以下内容。

//C#
if (!Page.IsPostBack)
{
 //should validate user input
 Document document = GetDocument(Request.QueryString["id"]);
 //We have the document, but can't edit it!
 if (!Locker.AcquireLock(document))
 {
  //let's add it to the user's list of docs to watch
  User.CurrentUser.AddDocumentToQueue(document.DocumentId);
  Response.Redirect("DocumentList.aspx");
 }
 //ok, we have the document and CAN edit it
 //...
}

键行是将文档添加到当前用户队列的位置,该队列会将文档添加到会话中。 接下来,我们将创建一个用户控件,该控件可以放置在任何页面上,用于在排队的文档可用时通知用户。 此用户控件将包含单个 AJAX 方法,以及向 AJAX 注册类所需的代码。

'VB.NET
Private Sub Page_Load(s As Object, e As EventArgs) 
                                   Handles MyBase.Load
 Ajax.Utility.RegisterTypeForAjax(GetType(UnlockNotifier))
End Sub

'Loops through the queued documents and checks if they're available
<Ajax.AjaxMethod()> _
Public Function GetUnlockedDocuments() As DocumentCollection
 'Get all the queued document ids belonging to the user
 Dim queuedDocument As ArrayList = User.CurrentUser.DocumentQueue
 Dim unlocked As DocumentCollection = New DocumentCollection

 For Each documentId As Integer In queuedDocumentIds
 'If the queued document is no longer locked
  If Not Locker.IsLocked(documentId) Then
   unlocked.Add(Document.GetDocumentById(documentId))
  End If
 Next

 Return unlockedDocuments
End Function

现在只需要一些 JavaScript 来发出请求并处理响应。 我们会将已发布的文档信息(如果有)放置在基于响应动态生成的表中。 为此,我们将从 HTML 开始。

<div id="notifyBox" style="display:none;">
 <b>The following queued documents can now be edited</b>
 <table cellpadding="5" cellspacing="0" 
       border="0" style="border:1px solid #EEE;" 
       id="notifyTable">
  </table>
</div>

当没有可用的文档 (或者没有任何文档排队供用户) 时,我们使用 DIV 标记隐藏所有内容,并使用 TABLE 标记来显示结果。 我们将使用轮询系统来查看是否有任何排队的文档可用。 基本上,这意味着我们会在延迟的情况下继续调用服务器端方法,并显示结果。 第一次调用只会在页面加载时发生,后续调用将每隔 X 秒进行一次。

<script language="javascript">
window.setTimeout("PollQueue();", 2000);
//fires every 2 seconds to check if a queued document was released
//in a real system with a lot of users, 2 seconds might put too high
//a load on the server. We could even check first to see if the user
//even has anything queued, but we'll certainly need to do some
//performance testing
function PollQueue()
{
 //UnlockNotifier is the type we registered with Ajax.NET
 //GetUnlockedDocuments is a method within that type marked with
 //the AjaxMethod attribute
 UnlockNotifier.GetUnlockedDocuments(PollQueue_CallBack);
 //calls itself every 2 seconds
 window.setTimeout("PollQueue();", 2000);
}
</script>

剩下的就是处理响应。 这类似于上一示例中的代码。 首先,检查任何错误,获取响应,循环访问可用文档,并动态生成 HTML,在本例中向表添加行和列。

function PollQueue_CallBack(response)
{
  var notifyBox = document.getElementById("notifyBox");
  var notifyTable = document.getElementById("notifyTable");
  //if we couldn't find our table notification box
  if (notifyBox == null || notifyTable == null)
  {
    return;
  }
  //if the server-side code threw an exception
  if (response.error != null)
  { 
    notifyBox.style.display = "none"; 
    alert(response.error); //we should probably do better than this
    return;
  }  
    
  var documents = response.value;
  //if the response wasn't what we expected    
  if (documents == null || typeof(documents) != "object")
  {
    notifyBox.style.display = "none";
    return;  
  }  
  for (var i = 0; i < notifyTable.rows.length; ++i)
  {
   notifyTable.deleteRow(i);
  }
  for(var i = 0; i < documents.length; ++i)
  {    
    var row = notifyTable.insertRow(0);
    row.className = "Row" + i%2;
    var cell = row.insertCell(0);
    cell.innerHTML = documents[i].Title;
    cell = row.insertCell(1);
    var date = documents[i].Created;
    cell.innerHTML = date.getDay() + "/" + date.getMonth() 
                     + "/" + date.getYear();
    cell = row.insertCell(2);
    cell.innerHTML = "<a href='DocumentEdit.aspx?id=" 
                     + documents[i].DocumentId + "'>edit</a>";
  } 
  notifyBox.style.display = "block"; 
}

我们将介绍的最后一个快速改进是在用户关闭浏览器、导航到其他链接或单击后退按钮时自动解锁正在编辑的文档。 通常,这是通过挂钩到 JavaScript OnBeforeUnLoad 事件或 OnUnload 事件,打开一个新的小弹出窗口,对页面加载执行一些清理,然后关闭自身来实现的。 虽然你自己使用弹出窗口可能是合法的,但其他人的播放不是那么好,导致弹出窗口阻止和文档永久保持锁定。 为了解决此问题,我们仍将依赖这两个 JavaScript 事件,但我们将通过 AJAX 执行服务器端方法,而不是启动弹出窗口。 在用于编辑文档的页面(即放置锁的页面上)上,我们添加了一些简单的 JavaScript。

<script language="javascript">
//Makes sure the document is unlocked if the user closes the 
//browser or hits the back button
window.onbeforeunload = ReleaseLock;
function ReleaseLock() {
 Locker.ReleaseDocument(<%=DocumentID%>);
}
</script>

此处, DocumentId 是在代码隐藏中定义和设置的变量。 或者,我们可以在会话中存储 DocumentId ,并在服务器端 ReleaseDocument 中对其进行访问。 ReleaseDocument 基本上从锁定的文档列表中删除该文档。

最后一个示例是修改现有应用。 我听说 乔希·莱德加德 最初提出这个想法,作为 MSDN 论坛的一项功能。 它的目标是尝试帮助有问题的用户帮助自己,以及限制重复帖子的数量。 基本上,当用户在论坛中提出新问题时,他或她会输入主题和问题,但通常不执行搜索来查看问题是否已被提出和回答。 输入 AJAX。 在用户输入完主题 (,并在字段) 外输入选项卡后,我们将基于主题异步搜索论坛,并且不明显地向用户显示结果。 有时,结果会有所帮助,有时则无济于事。

为此,我们将修改 asp。NETPRO 读者选择奖最佳论坛应用程序社区服务器。 可下载的示例不包括本节 (或论坛) 中的代码,但你可以通过 http://communityserver.org/ 了解有关 CommunityServer 的详细信息,并向其应用以下代码片段。

安装 CommunityServer 并 Ajax.NET 配置 (引用和处理程序添加到 web.config) 后,只需进行一些更改即可获得所需的功能。 首先,转到 CommunityServerForums 项目中的 CreateEditPost.cs 文件。 将此视为用户在其中添加新帖子的页面的代码隐藏。 在这里,我们将添加已启用 AJAX 的函数。

//C#
[Ajax.AjaxMethod()]
public static ArrayList Search(string search)
{
 SearchQuery query = new SearchQuery();
 query.PageIndex = 0; //get the first 10 results
 query.PageSize = 10;
 query.UserID = Users.GetUser().UserID;
 query.SearchTerms = search;
 return new ForumSearch().GetSearchResults(query).Posts;
}

我们能够利用已内置于 CommunityServer 中的搜索功能,并简单地让函数围绕它进行包装。 与往常一样,类型必须注册到 Ajax.NET。 我们将在同一文件的 InitializeSkin 函数中执行此操作, (将其视为Page_Load) 。

//C#
Ajax.Utility.RegisterTypeForAjax(typeof(CreateEditPost));

在跳转到 JavaScript 之前,我们需要进行最终的服务器端更改。 返回到 Ajax.NET 的自定义类(如我们返回的 ArrayList 中包含的 ForumPost)必须使用 Serializable 属性进行标记。 我们只需转到 CommunityServerForums 项目的 Components/ForumPost.cs 文件,然后添加 属性。

//C#
[Serializable]
public class ForumPost : Post
{
 ...
}

在演示端,我们只需要修改 CommunityServerWeb 项目中的 Themes/default/Skins/View-EditCreatePost.cs。 首先,我们将挂钩到主题文本框的 onBlur 事件。

<asp:textbox onBlur="Search(this.value);" 
             id="PostSubject" runat="server" ... />

接下来,我们编写 JavaScript 搜索 方法,以便它调用服务器端 搜索

var oldValue = '';
function Search(value)
{ 
  //don't search again for something we just searched
  //would happen if the user is tabbing back and forth
  if (value != oldValue)
  {
   CreateEditPost.Search(value, Search_CallBack);
   oldValue = value;
  }
}

最后,剩下的就是处理响应。 由于上一个示例演示了在表中显示结果的稍微简洁的方式,因此我们只需创建一些动态 HTML 并将其粘在虚构的 DIV 中。

function Search_CallBack(response)
{
 //since the search functionality automatically redirects if there 
 //are no results, we can't rely on response.error

 var results = response.value;
 //if we didn't get a result
 if (results == null)
 {
  return;
 }

 //a div that we'll use to put our results
 var someDiv = document.getElementById("someDiv");  
 var html = "";
 for (var i = 0; i < results.length; ++i)
 {
  var result = results[i];
  html += "<a target=_blank href='" + result.PostID
  html += "/ShowPost.aspx'>";   
  html += result.Subject;
  html += "</a><br />"
 }
 someDiv.innerHTML = html;
}

通过对三个文件进行少量修改, (加上 CommunityServer 应用程序的配置) web.config,我们能够添加一些漂亮的功能。 但是,请务必谨慎将已启用 AJAX 的功能添加到现有应用程序。 执行实际搜索的预先存在的 ForumSearch 类可能不是针对我们引入的使用类型设计的。 我们的代码可能会导致执行大量额外的搜索,并且影响可能很大。

AJAX 和 You

AJAX 如何和在哪里适合你的应用程序,以及它们是否已经存在,将是非常符合情况的。 尽管我们已看到使用 Ajax.NET 创建支持 AJAX 的解决方案是多么容易,但还有其他注意事项需要考虑。 一个严重的问题是对应用程序的整体体系结构和可维护性的影响。 AJAX 可以进一步模糊系统层之间的界限,尤其是表示层、呈现逻辑层和业务层。 这不是 AJAX 本身的问题,而是如何使用它的问题。 只要你意识到这是多么容易导致层之间的一些出血,并且只是计算上这样做,一切都应该是好的。

使用 AJAX 的应用程序是否会更难维护? 答案在很大程度上取决于你已在使用多少 JavaScript,以及你对组织和维护 JavaScript 的出色程度。 许多开发人员认为 JavaScript 更难编写、测试和调试 (不是因为 JavaScript 本身,而是因为工具支持和开发人员知识) 。 如果当前正在使用 JavaScript 实现链接下拉列表,并切换到 AJAX,则代码可能会更容易维护 (Ajax.NET 对 .NET 类型和数组的支持是此) 的一个重要原因。 但是,如果要采用后退路线,现在将 (JavaScript) 向应用程序引入一种全新的语言,并且必须处理一些数据未参与 ViewState (,正如我们在按钮单击事件) 中看到的那样。

另一个注意事项是 AJAX 对网站可用性的影响。 尽管 AJAX 的最终礼物是创建响应性更高的接口,但开发人员应记住两点。 首先,最明显的是,AJAX 依赖于 JavaScript。 我们都知道,一些用户禁用 JavaScript,并且某些标准 (,例如加拿大政府的 Common Look and Feel [认为加拿大的 508]) 要求网站使用或不使用 JavaScript。 因此,不应假设 AJAX 功能正常工作,如果应用程序不可用,则应让应用程序回退到更正常的 Web 处理。 其次,AJAX 应用程序可能不熟悉 (即使它比用户习惯使用应用程序的方式) 优越。 例如,通过 AJAX 执行各种操作的页面可能与“后退”按钮、“收藏夹”菜单和其他浏览器功能的行为不一样,就像用户认为的那样。

结论

AJAX 不仅仅是一种被炒作的即将推出的技术;相反,它是一个具体的框架,可以为生成 Web 应用程序时的日常问题提供替代解决方案。 Ajax.NET 使 ASP.NET 开发人员可以轻松接受 AJAX。 我们查看的三个示例以及可下载的项目旨在帮助你了解如何使用 AJAX 和 Ajax.NET,并提供一个简单的演练,供你尝试一些自己的想法。 AJAX 不仅仅是创建整洁酷的应用程序;它可以真正提高客户满意度和竞争优势。 为 Atlas 讨论的一些高级概念可以显著改进我们提供的产品。 就我个人而言,我见过的最佳 AJAX 实现相当轻量级,感觉不错。 对于用户来说,你自己的实现应该是同样积极的体验。 但请记住,鉴于存在问题,AJAX 可能不是唯一的解决方案,也可能不是最佳解决方案。 现在,让我们证明 ASP.NET 社区是首屈一指的,让我们干净的房子。

 

关于作者

Karl Seguin 将大部分时间花在 Microsoft ASP.NET 新闻组上,帮助其他开发人员,并寻找有用的主题进行撰写。 当他不工作或帮助时,他正在无情地清洁格诺米什鼠疫的阿泽罗斯。

© Microsoft Corporation. 保留所有权利。