65.9K
CodeProject 正在变化。 阅读更多。
Home

(重新)使用 Prototype 框架为 ASP.NET 引入 AJAX

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (13投票s)

2008 年 12 月 17 日

CPOL

10分钟阅读

viewsIcon

62910

downloadIcon

464

在 ASP.NET 应用程序中编写和使用跨平台 AJAX。

AJAXMadeSimple

引言

ASP.NET 平台无疑是一个以服务器为中心的模型,它从未打算执行像异步 JavaScript 和 XML (AJAX) 这样的客户端密集型逻辑。为了向 .NET 社区提供 AJAX 框架,同时又不疏远那些花费了职业生涯来针对这种基于服务器的架构进行编程的开发人员,微软需要找到一种方法,使客户端 JavaScript 能够轻松地使用现有的服务器控件标准进行开发。最终,他们交付了一个适用于 ASP.NET 的 AJAX 框架,让 .NET 开发人员能够体验到许多开发人员早已享受到的一些东西。

重要的是要理解,ASP.NET AJAX 是众多框架中的一种,而且存在着大量的 AJAX 框架(超过 100 个)。

本文演示了如何在 ASP.NET 应用程序中使用一个替代的 JavaScript/AJAX 框架进行 AJAX 开发。

JavaScript 和 Prototype 框架

尽管本文的范围仅限于 AJAX,但我还是想花点时间讨论一下 JavaScript,以及为什么存在包装 JavaScript 的框架。

在 Web 技术爆炸式发展之前,似乎一夜之间,几乎所有的开发人员都创建了针对特定平台设计的代码。他们使用的工具有效地实现了语言规范,并且可以专注于性能和优化例程。而编写 JavaScript 可能会很痛苦和乏味,这并非因为语言本身,而是因为其他语言用于与 JavaScript 通信的 API,尽管已标准化,但并非所有平台都能完全实现。换句话说,有些浏览器可以做而另一些浏览器不能做的事情。

有些平台甚至错误地实现了某些规范(例如 IE 中的 DOM 规范),这可能导致内存泄漏和其他非常难以排查的问题。开发人员很容易将一半工作时间用于开发跨平台 JavaScript 代码,而另一半时间则用于调试。对于大多数开发人员来说,即使应用程序性能的提升可能很显著,但让他们觉得不值得去处理 JavaScript。

不愿放弃 JavaScript 的潜力,许多开发人员开始编写“辅助”方法,以执行单调的任务,例如检查浏览器版本和根据浏览器版本设置变量。其中一些“辅助”框架开始被共享、同行评审并优化到可以被视为企业级框架的程度。Prototype 框架就是这些如今被广泛使用且备受推崇的框架之一。事实上,它被 NASA、CNN、Ruby On Rails 和 Apple 等商业机构使用。

Prototype 不是像 script.aculo.us 这样的组件、UI 或控件库,它是驱动组件库的引擎。Prototype 是许多库在其之上分层的基石。它不关注任何具体的实现(例如拖放 AJAX 控件),而是关注抽象和面向对象编程 (OOP) 原则,使您能够以最快、最可靠的方式构建这些控件。

当您开始使用 Prototype 并逐渐理解它的简洁和优雅时,您会发现很难回到纯粹的原生 JavaScript。

深入阅读

AJAX 和 Prototype 框架

当然,AJAX 是异步 JavaScript 和 XML,它实际上只是意味着开发人员正在利用 JavaScript 的 `XmlHttpRequest` 对象。这个对象允许浏览器在标准的页面请求范围之外发起页面请求。更重要的是,它允许您在不刷新整个页面的情况下刷新页面的部分内容。`XmlHttpRequest` 对象位于客户端,可以在不干扰托管 Web 服务器的情况下与服务器进行数据传输。`XmlHttpRequest` 并不直观,而且使用起来可能非常令人沮丧,尤其是在处理跨浏览器已知问题(更不用说编写大量的代码)时。Prototype 在这方面为我们做得非常好,并公开了一个简单而强大的 AJAX API,涵盖了开发人员想要的几乎所有原始 AJAX 功能。

Prototype 为我们提供了一个清晰的 AJAX 接口供我们利用。提供的方法有:

就本文而言,我们将使用 `Ajax.PeriodicUpdater` 和 `Ajax.Request` 方法,因为成员之间存在功能重叠,而且它们是 Prototype 的 AJAX 包装器中最常用的调用。

示例

这些示例的目的是演示在您的应用程序中使用 Prototype 框架进行异步部分回发的各种方法。在 AJAX 开发方面,几乎所有的 AJAX 都用于相同的目的:

  • 作为页面事件(按钮点击等)的响应,异步更新页面上的一个区域,并且仅刷新该区域。
  • 按定时器异步更新页面上的一个区域,并且仅刷新该区域。

包含的示例每个都包含两部分:客户端用户界面和服务器脚本。其工作方式如下:`ClientUI.aspx` 页面由客户端使用,就像使用任何其他页面一样。当它们与 AJAX 控件交互时,控件会异步执行“GET”请求到服务器脚本,并且根据服务器的响应,AJAX 控件会默默地更新需要更新的页面区域。

包含的示例是:

  • 行情自动更新器
  • 行情自动更新器项目使用 `Ajax.PeriodicUpdater` Prototype 方法,根据定时间隔异步更新页面上的一个区域。解决方案包括一个获取文本文件中的行情的服务器脚本,以及一个使用 AJAX 每 5 秒执行一次“GET”请求到服务器脚本的客户端页面。

  • 自动建议
  • 自动建议项目介绍了 `Ajax.Request` Prototype 方法,该方法用于基于事件执行 AJAX 请求。在这种情况下,当用户在启用 AJAX 的输入框中键入字母时,将触发一个事件,该事件会向服务器脚本发出异步“GET”请求,以便在 XML 文件中查找匹配的记录。用户在输入框中键入时会看到建议列表,如果他们单击某个建议,则会调用一个 JavaScript 函数来尝试播放选定的记录在 Windows Media Player 中。

  • 媒体播放器
  • 音乐/电影播放器项目也使用了 `Ajax.Request` Prototype 方法,但它不需要服务器脚本即可运行。对于这个示例,我们使用了一个现有的 XML 文件,并直接从 JavaScript 与其交互,省略了服务器端处理器的需要。

`prototype.js` 框架包含在 `/AJAXMadeSimple/js` 文件夹的示例中。

行情自动更新器

注意:此示例可在 `/AJAXMadeSimple/AJAXRandomQuote` 中找到。

`AJAXRandomQuote` 项目演示了如何使用 Prototype 库中的 `PeriodicUpdater` 方法来创建一个在定时间隔内自动更新的页面区域。我们为此使用了名言,但它通常用于新闻和 RSS 项目以及股票行情列表。

QuoteScript.aspx (服务器脚本)

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.IO" %>

<script runat="server" >
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.ContentType = "text/plain";
        Response.CacheControl = "no-cache";
        Response.AddHeader("Pragma", "no-cache");
        Response.Expires = -1;
        
        Random rnd = new Random();
        List<string> qs = GetQuotes();
        Response.Write(qs[rnd.Next(qs.Count)]);
    }

    private List<string> GetQuotes()
    {
        List<string> q = new List<string>();
        string qfile = Server.MapPath("quotes.txt");

        if (File.Exists(qfile))
        {
            using (StreamReader sr = new StreamReader(qfile))
            {
                string line = string.Empty;
                while ((line = sr.ReadLine()) != null)
                {
                    if (!string.IsNullOrEmpty(line))
                        q.Add(line);
                }
            }
        }
        return q;
    }    
</script>

上面的脚本用于从服务器上的文本文件中读取并向客户端返回一个随机行(每次脚本执行时)。请注意 `ContentType`、`CacheControl` 和 `Header` 属性的存在,这些属性必须设置才能使示例正确工作。我们必须强制服务器拒绝(任何形式的)缓存,以确保我们的客户端每隔几秒钟就能获得一个新的行情。当然,我们可以从任何地方(数据库、XML 文件、文本文件等)获取这些数据。

延伸阅读: MSDN - 如何防止 Internet Explorer 缓存

ClientUI.aspx (客户端页面)

<%@ Page Language="C#"%>

<!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>
    <title>Untitled Page</title>
    <script src="../js/prototype.js" type="text/javascript"></script>
</head>
<body>
<div id="quote"></div>
<p>
<input type="button" onclick="stopPolling()" value="Stop Ajax" /> 
<input type="button" onclick="startPolling()" value="Start Ajax"  />
    
<script language="javascript" type="text/javascript" >
var poller;

poller = new Ajax.PeriodicalUpdater('quote', 'QuoteScript.aspx', {
  method: 'get', frequency: 5
});

function stopPolling() {
  poller.stop();
  $(quote).innerHTML = "Asynchronous JavaScript Stopped";
}

function startPolling() {
  poller.start();
}

</script>
</body> 
</html>

您可以看到这是一个非常简单的页面,它由页面上的一个 `#div` 区域来容纳我们的引语、几个输入按钮控件以及 AJAX `periodicUpdater` 组成。

new Ajax.PeriodicalUpdater(container, url[, options])

我们将容器参数定义为 `quote`(我们的 `#div` 区域),将 url 参数定义为 `QuoteScript.aspx`(我们的服务器脚本)。我们正在使用选项:`method` 和 `frequency`。`Method` 定义我们的操作,`frequency` 以秒为单位定义更新时间。实际上,我们希望每 5 秒从服务器接收一个新的引语。

深入阅读

自动建议文本输入

注意:此示例可在 `/AJAXMadeSimple/AJAXAutoSuggestBox` 中找到。

AJAX 最令人兴奋的功能之一是能够在不中断用户体验的情况下在后台执行任务。这种异步处理可以让你做很多很棒的事情来提高用户满意度(例如,搜索建议、自动完成下拉列表)。`AJAXAutoSuggestBox` 项目演示了如何为用户提供他们输入搜索字段时建议搜索。建议源于服务器脚本的响应(该脚本正在读取 XML 文件)。

ServerSearch.aspx (服务器脚本)

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Xml.Linq" %>
<%@ Import Namespace="System.Linq" %>

<script runat="server" >
    protected void Page_Load(object sender, EventArgs e)
    {
        //You must specify the ResponseType as Xml
        Response.ContentType = "text/xml";
        string qs = Request.QueryString["q"];
        
        if (!string.IsNullOrEmpty(qs))
        {
            //Search the Xml data source and create the response
            Response.Write("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
            Response.Write("<music>");
            XDocument xdoc = XDocument.Load(Server.MapPath("player.xml"));
            var query = from s in xdoc.Elements("music").Elements("Track")
                        where s.Attribute("url").Value.Contains(qs)
                        select s;

            foreach (XElement xe in query.ToList())
                Response.Write(xe.ToString());

            Response.Write("</music" + ">");
        }
    }    
</script>

这个服务器脚本比上一个要复杂一些,因为我们需要向 AJAX 客户端返回格式正确的 XML。请注意 `Response.ContentType` 属性,因为它必须指定服务器响应是 XML,而不是纯文本或 HTML。我们使用新的 `System.Xml.Linq` 类来快速搜索 XML 文件,然后创建一个仅包含查询结果的新 XML 文件(以反馈给 AJAX 客户端请求)。

深入阅读

ClientUI.aspx (客户端页面)

<%@ Page Language="C#"%>
<!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 id="Head1" runat="server"><title>Partial Page Post Back Example - Music Player</title>
<script src="../js/prototype.js" type="text/javascript"></script>
</head>
<body>
<input type="text" id="q" onkeyup="search()"  />
<div id="songs" ></div><p> </p>
<div id="player"></div>
    
<script language="javascript" type="text/javascript" >
function PlaySong(url)
{
  $('player').innerHTML = '';
  var m_embed = document.createElement('embed');
  m_embed.src = url;
  $('player').appendChild(m_embed);
}

function search() {
new Ajax.Request('ServerSearch.aspx?q='+escape($F('q')), {
  method: 'get', 
  onSuccess: function(transport) {
    var trackXml = transport.responseXML.getElementsByTagName('Track');
    
    $('songs').innerHTML = '';

    for(var x = 0; x < trackXml.length; x++) {
      var url = trackXml[x].getAttribute('url');
      var title = trackXml[x].getAttribute('title');
      var artist = trackXml[x].getAttribute('artist');
      
      var html = '<a href="javascript:void PlaySong(\''+ url +'\');" class="link">';
      html += artist + ' - ' + title +'</a><br />';
      $('songs').innerHTML += html;
      }
    }
  } );
}        
</script>
</body> 
</html>

这个客户端脚本也比之前的客户端脚本复杂一些,但仔细看,你会发现它实际上很简单。我们定义了一个输入文本字段,它在每次输入键时运行 `search()` 函数,一个 `#div` 元素来存储 AJAX 自动建议,一个 `#div` 元素来存储 Windows Media Player (WMP),以及两个 JavaScript 函数:

  • PlaySong(url)
  • 如果您不想看到 AJAX 媒体播放,可以完全忽略它。它仅在 IE 中有效,我们所做的就是创建一个 `embed` 元素到我们的播放器 `#div` 中,并告诉嵌入的媒体播放器我们想要播放的音乐文件的位置。

  • search()
  • `search` 函数引入了 `Ajax.Request` prototype 方法(该库中最常用的方法)。

new Ajax.Request(url[, options])

我们将 `ServerSearch.aspx` 页面指定为我们的 URL(带有基于搜索输入字段值的查询字符串),并使用 `options` 参数:`method` 和 `onSuccess`。如果请求成功,我们将服务器返回的响应 XML 流分配给一个变量(`trackX`ml)。我们枚举响应 XML 流,提取我们需要创建匹配歌曲列表的元素,并创建播放选定曲目所需的链接。

player.xml (数据源)

<?xml version="1.0" encoding="utf-8" ?>
<music>
  <Track url="03_metallica_-_broken_beat_scarred.mp3" 
         artist="Metallica" title="Broken, Beat, Scarred"></Track>
  <Track url="05_metallica_-_trapped_under_ice.mp3" 
         artist="Metallica" title="Trapped Under Ice"></Track>
  <Track url="06_metallica_-_harvester_of_sorrow.mp3" 
         artist="Metallica" title="Harvester of Sorrow"></Track>
</music>

深入阅读:

AJAX 音乐/电影播放器

注意:此示例可在 `/AJAXMadeSimple/AJAXMusicPlayer` 中找到。

`AJAXMusicPlayer` 项目是 `AJAXAutoSuggestBox` 的一个更简单的分支。在这个项目中,我们不需要服务器脚本来为我们进行任何处理,因为我们将使用服务器上现有的 XML 数据源。与上述情况一样,在 HTML `embed` 标签中实际播放音乐或电影依赖于使用支持它的浏览器(如 IE),在现实世界中,您永远不会这样做,但这有效地展示了 AJAX 如何为您的业务解决方案提供动力。

如上所述,此示例不需要服务器脚本。

ClientUI.aspx (无需服务器脚本!)

<%@ Page Language="C#" %>

<!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>Partial Page Post Back Example - Music Player</title>
    <script src="../js/prototype.js" type="text/javascript"></script>
    <link href="player.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="songs" class="songs"></div><p></p>
<div id="player"></div>
    
<script language="javascript" type="text/javascript" >
function PlaySong(url)
{
  $('player').innerHTML = '';
  var m_embed = document.createElement('embed');
  m_embed.src = url;
  $('player').appendChild(m_embed);
}

new Ajax.Request('player.xml', {
  method: 'get',
  onSuccess: function(transport) {
    var trackXml = transport.responseXML.getElementsByTagName('Track');
    
    $('songs').innerHTML = '';

    for(var x = 0; x < trackXml.length; x++) {
      var url = trackXml[x].getAttribute('url');
      var title = trackXml[x].getAttribute('title');
      var artist = trackXml[x].getAttribute('artist');
      
      var html = '<a href="javascript:void PlaySong(\''+ url +'\');" class="link">';
      html += artist + ' - ' + title +'</a><br />';
      $('songs').innerHTML += html;
      }
    }
  }  );        
</script>
</body>
</html>

这基本上与 `AJAXAutoSuggestBox` 脚本相同,只是我们指定了要使用的 XML 文件,没有输入字段,并且曲目列表在页面加载时显示。当我们单击一个曲目时,URL 会被放入一个 `embed` 元素中,并且曲目开始播放。所有这些逻辑都在没有页面回发或重新渲染的情况下执行。一切都在客户端完成。

有关更多解释和进一步的阅读资源,请参阅上面的 `AJAXAutoSuggestBox` 部分。

player.xml (数据源)

<?xml version="1.0" encoding="utf-8" ?>
<music>
  <Track url="03_metallica_-_broken_beat_scarred.mp3" 
         artist="Metallica" title="Broken, Beat, Scarred"></Track>
  <Track url="05_metallica_-_trapped_under_ice.mp3" 
         artist="Metallica" title="Trapped Under Ice"></Track>
  <Track url="06_metallica_-_harvester_of_sorrow.mp3" 
         artist="Metallica" title="Harvester of Sorrow"></Track>
</music>

深入阅读

Scriptaculous

如前所述,script.aculo.us 是一个强大的框架,它建立在 `prototype.js` 之上,并提供令人惊叹的特效,如动画、拖放、DOM 和单元测试,以及大量其他很棒的功能。如果本文反响良好,我可以撰写一篇类似的关于在 ASP.NET 中使用 Scriptaculous 的示例文章。

结论

在本文中,我们演示了如何在不要求 ASP.NET AJAX 框架的情况下,将强大的 AJAX 功能实现到 ASP.NET 网站中。使用 Prototype 框架的可能性是无限的,而且几乎不需要多少 JavaScript 知识就可以立即开始获得结果。

历史

  • 2008/12/17 - 文章提交。
© . All rights reserved.