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






4.62/5 (73投票s)
本文介绍了一种在 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 应用程序自己的页面或服务。
所有这些考虑因素都在下图中有说明:
实现
基本的 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_Prerender
或 Page_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,他们在我测试和优化文章中描述的方法时给予了帮助。