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

ASP.NET Web 应用程序的简单 AJAX 实现

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.62/5 (73投票s)

2006年4月5日

CPOL

6分钟阅读

viewsIcon

351156

本文介绍了一种在 ASP.NET Web 应用程序中实现 AJAX 功能的简单方法。

引言

本文档描述了一种在 ASP.NET Web 应用程序中实现 AJAX 功能的简单方法。文章还讨论了使用 AJAX 的优缺点。文档包含一个可用的 JavaScript 和 C#.NET 代码,演示了建议的解决方案。

为什么选择 AJAX

你们大多数人可能已经知道 AJAX 代表异步 JavaScript 和 XML。据我所知,这项技术最早由微软于 1999 年推出,当时被称为“具有远程调用的 DHTML / JavaScript Web 应用程序”。该技术的核心思想是允许 Internet 浏览器向远程页面/服务发出异步 HTTP 调用,并在不刷新整个页面的情况下使用收到的结果更新当前 Web 页面。根据创建者的观点,这应该能改善用户体验,使 HTTP 页面看起来和感觉都非常像 Windows 应用程序。

由于该技术的核心实现基于 Internet 浏览器功能,因此当时的可用性非常有限。但几年后,随着新浏览器的支持以及 Google、Amazon.com、eBay 等巨头的广泛实施,这项技术得以重生。

如今,它被称为 AJAX,并被认为是任何具有高级用户体验的动态 Web 页面的自然组成部分。

解决方案描述

建议的方法提供了一种非常简单但有效的 AJAX 功能实现。它易于维护和更改,不需要开发人员具备任何特殊技能,并且据我们所知,它是跨浏览器兼容的。

基本上,一个常规的类 AJAX 实现包含两个主要组件:一个带有 JavaScript 代码的客户端 HTML 页面,用于发出 AJAX 调用并接收响应;以及一个可以接受请求并以所需信息响应的远程页面。客户端页面上的 JavaScript 代码负责实例化一个 XmlHttp 对象,然后为该对象提供一个回调方法,该方法将负责处理收到的信息,最后,通过 XmlHttp 对象将请求发送到远程页面。所有这些都由 JavaScript 代码完成。

我们的方法旨在用于 ASP.NET 应用程序,并考虑了以下可能的场景:

  • AJAX 调用可能从 Web 应用程序的不同 ASP.NET 页面调用不同的远程页面;
  • 远程页面的 URL 可能包含动态计算的参数,并且在 ASP.NET 页面的代码隐藏中构建 URL 字符串可能更方便;
  • 远程页面可能响应复杂的数据,需要进行解析才能更新 HTML 页面,而这又可以在 ASP.NET 页面的代码隐藏中完成;
  • 远程页面可以是外部第三方页面,也可以是 Web 应用程序自己的页面或服务。

所有这些考虑因素都在下图中有说明:

Solution diagram

实现

基本的 AJAX JavaScript 方法

我将所有 JavaScript 方法分为两部分:调用页面特定的 JavaScript 方法,以及所有调用页面通用的 AJAX JavaScript 方法。特定方法包括回调方法,因为它负责更新页面内容。通用的 AJAX 方法负责实例化 XmlHttp 对象并向远程页面发送异步请求。

获取 XmlHttp 对象取决于浏览器类型。我区分两种基本类型:Microsoft 浏览器,属于 IE 系列;以及 Mozilla 浏览器,属于 Mozilla Firefox、Netscape 或 Safari。我也测试了 Opera 浏览器,但不保证它总是能正常工作。

function GetXmlHttpObject(handler)
{ 
    var objXmlHttp = null;
    if (!window.XMLHttpRequest)
    {
        // Microsoft

        objXmlHttp = GetMSXmlHttp();
        if (objXmlHttp != null)
        {
            objXmlHttp.onreadystatechange = handler;
        }
    } 
    else
    {
        // Mozilla | Netscape | Safari

        objXmlHttp = new XMLHttpRequest();
        if (objXmlHttp != null)
        {
            objXmlHttp.onload = handler;
            objXmlHttp.onerror = handler;
        }
    } 
    return objXmlHttp; 
} 

function GetMSXmlHttp()
{
    var xmlHttp = null;
    var clsids = ["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0",
                 "Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0", 
                 "Msxml2.XMLHTTP.2.6","Microsoft.XMLHTTP.1.0", 
                 "Microsoft.XMLHTTP.1","Microsoft.XMLHTTP"];
    for(var i=0; i<clsids.length && xmlHttp == null; i++) {
        xmlHttp = CreateXmlHttp(clsids[i]);
    }
    return xmlHttp;
}

function CreateXmlHttp(clsid) {
    var xmlHttp = null;
    try {
        xmlHttp = new ActiveXObject(clsid);
        lastclsid = clsid;
        return xmlHttp;
    }
    catch(e) {}
}

根据 Umut Alev 的说法,考虑到我们不必引用 MSXML5(因为它仅设计用于 Office 应用程序),GetMSXmlHttp 方法的代码可以得到简化。相应地,GetMSXmlHttp 方法的简化版本可能如下所示:

function GetMSXmlHttp() {
    var xmlHttp = null;
    var clsids = ["Msxml2.XMLHTTP.6.0",
                  "Msxml2.XMLHTTP.4.0",
                  "Msxml2.XMLHTTP.3.0"];
    for(var i=0; i<clsids.length && xmlHttp == null; i++) {
        xmlHttp = CreateXmlHttp(clsids[i]);
    }
    return xmlHttp;
}

正如您所见,GetXmlHttpObject 方法接受一个处理程序参数,该参数是页面特定代码中应定义的​​回调方法的名称。现在我们已经有了一个 XmlHttp 对象,我们可以发送一个异步请求。

function SendXmlHttpRequest(xmlhttp, url) { 
    xmlhttp.open('GET', url, true); 
    xmlhttp.send(null); 
}

我使用 GET HTTP 方法访问给定 URL,但这可以通过更改上面的 JS 代码轻松修改。

特定页面方法

现在我们有了执行远程页面调用所需的所有方法。为了做到这一点,我们需要将回调方法名传递给 GetXmlHttpObject 方法,然后将 URL 字符串传递给 SendXmlHttpRequest 方法。

var xmlHttp; 

function ExecuteCall(url)
{ 
    try 
    { 
        xmlHttp = GetXmlHttpObject(CallbackMethod); 
        SendXmlHttpRequest(xmlHttp, url); 
    }
    catch(e){} 
} 
    
//CallbackMethod will fire when the state 

//has changed, i.e. data is received back 

function CallbackMethod() 
{ 
    try
    {
        //readyState of 4 or 'complete' represents 

        //that data has been returned 

        if (xmlHttp.readyState == 4 || 
            xmlHttp.readyState == 'complete')
        {
            var response = xmlHttp.responseText; 
            if (response.length > 0)
            {
                //update page

                document.getElementById("elementId").innerHTML 
                                                   = response; 
            } 
        }
    }
    catch(e){}
}

CallbackMethod 负责更新页面内容。在我们的示例中,它只是更新给定 HTTP 元素的内部 HTML。但在实际应用中,它可能会复杂得多。

关于调用页面实现的最后一个问题是如何调用 ExecuteCall JS 方法。嗯,这取决于页面的功能。在某些情况下,可以在 JS 事件触发时调用 ExecuteCall 方法。但如果不是这种情况,我们可以使用页面代码隐藏中的相应 C# 代码将该方法注册为页面的启动脚本。

Page.RegisterStartupScript("ajaxMethod", 
   String.Format("<script>ExecuteCall('{0}');</script>", url));

我们可以将此行代码添加到 ASP.NET 代码隐藏文件的 Page_PrerenderPage_Load 方法中。

远程页面

让我们看看远程页面可能是什么样的。如果这是一个 ASP.NET 页面(我们假设如此),我们只对代码隐藏感兴趣。我们可以轻松删除 .aspx 文件中的所有代码:它不会以任何方式影响页面的行为。

例如,我们采用一个公共 Web 服务,该服务可以将摄氏度转换为华氏度,反之亦然。该服务可通过此处访问。如果您将此 URL 添加为项目的 Web 引用,Visual Studio 将在当前命名空间中生成一个名为 com.developerdays.ITempConverterservice 的代理类。我们的远程 ASP.NET 页面(我们称之为 getTemp.aspx)将接受一个名为“temp”的查询字符串参数,该参数应包含要转换的摄氏度温度的整数值。因此,到远程页面的目标 URL 将如下所示:https:///getTemp.aspx?temp=25。该页面的代码隐藏如下所示:

private void Page_Load(object sender, EventArgs e)
{
    Response.Clear();
    string temp = Request.QueryString["temp"];
    if (temp != null)
    {
        try
        {
            int tempC = int.Parse(temp);
            string tempF = getTempF(tempC);
            Response.Write(tempF);
        }
        catch
        {
        }
    }
    Response.End();
}

private string getTempF(int tempC)
{
    com.developerdays.ITempConverterservice 
          svc = new ITempConverterservice();
    int tempF = svc.CtoF(tempC);
    return tempF.ToString();
}

根据我们的约定,现在我们可以为远程页面构建一个 URL 字符串,然后在上面的示例中将其传递给 RegisterStartupScript 方法,如下所示:

int tempC = 25;
string url = String.Format("https:///" + 
             "getTemp.aspx?temp={0}", tempC);

使用中间 ASP.NET 页面(然后调用远程服务)的方法可以简化响应处理,特别是当它需要解析时。在响应仅包含文本的简单情况下,我们可以将远程服务 URL 直接传递给 JS ExecuteCall 方法。

结论

本文旨在说明在任何 ASP.NET 应用程序中使用 AJAX 技术的简便性。虽然 AJAX 存在一些缺点,但从用户体验的角度来看,它也提供了一些优势。是否使用 AJAX 技术完全取决于开发人员,但我刚刚证明在简单的情况下,这不需要花费很长时间或具备任何特殊技能。

致谢

我想感谢我的同事 Oleg Gorchkov 和 Chris Page,他们在我测试和优化文章中描述的方法时给予了帮助。

© . All rights reserved.