使用 Prototype AJAX 框架结合 HTML 和 ASP.NET Web 项目
使用 Prototype 框架调用 ASP.NET 页面。
引言
我最近有一个需求,需要从一个网站的页面中抓取 HTML 片段,并将其包含在另一个网站的某些页面中。我无法通过将任一站点设置为 ASP.NET Web 项目来实现此目的,因为我们的内容管理系统要求源页面和目标页面都必须保留为 HTML 文件,而不能包含在 ASP.NET Web 项目中。两个网站都由我控制,所以我对它们拥有完全的访问权限,但它们位于不同的域上。
我相当确定我可以使用 AJAX 来实现这一点,所以我做了一些研究。我生性懒惰,所以我不想编写自己的 XMLHTTPRequest
代码,而是可以获得简单易用的开源代码来为我完成工作。经过一番搜索和阅读,我选择了 Prototype 框架,因为它看起来易于使用,并且拥有良好的文档和示例。它似乎也很受欢迎,并且有一个活跃的社区,因此如果需要,可以获得帮助。
跨域问题
我的第一个问题是跨域访问页面。如果我尝试从不同的域读取文件,大多数浏览器会将其视为安全漏洞并弹出警告(至少),或者拒绝加载页面。由于我完全控制这两个域,最简单的解决方案是将源页面上传到我需要调用它们的域。两个网站都在我的内部服务器上设有暂存站点,并且每小时都会自动上传到生产服务器。这对我来说绰绰有余,所以我只是创建了另一个上传作业,如果源页面发生更改,就会将它们传输到第二个域。
太好了,现在页面就在我需要的地方了,再也没有跨域调用了。下一步,从源页面中提取 HTML 片段。
ASP.NET 项目
这就是 ASP.NET 项目发挥作用的地方。(我非常感谢 Christian Graus 在此过程中提供的帮助)。虽然我不能将整个网站都变成 ASP.NET 项目,但我可以将一个 ASP.NET 项目作为子目录中的一个应用程序。内容作者不会对项目中的任何文件进行任何更改,当我编译和发布项目时,VS 可以覆盖子目录而不会影响网站的其余部分。我所要做的就是为每个 HTML 源页面创建一个空的 ASPX 文件。ASPX 页面只需要 @Page
指令和 CodeFile
和 Inherits
属性。删除所有其他内容(包括 <html>
、<head>
和 <body>
标签)。
<%@ Page Language="VB" AutoEventWireup="false"
CodeFile="Test.aspx.vb" Inherits="Test" %>
然后,在代码隐藏的 OnPageLoad
事件中,一些读取源页面并抓取所需 HTML 的代码使用 Response.Write
输出它。诀窍是在代码末尾添加一个 Response.End
,这样除了所需的 HTML 片段之外,您不会得到任何其他返回内容。为了识别所需的片段,我使用了几个命名锚点来标记 HTML 中的起始和结束点(<a id=”TheStart”></a>
和 <a id=”TheEnd”></a>
)。为了让我的生活更轻松,我编写了一个简单的类,其中包含所有页面名称和源页面路径,以及一些通用代码,用于抓取开始标签和结束标签之间的所有内容。它还会将任何图像标签或相对超链接重新定位回原始域,以便它们在新页面中仍然有效。
文章顶部提供了示例项目下载。我使用了 VB.NET,但语言无关紧要——AJAX 代码只看到 HTML 片段。
AJAX 部分
太棒了,现在我有了我需要的片段,我所要做的就是将它们放入页面。事实证明,这是最简单的步骤。我编写了一小段 JavaScript,并将其保存在我的Scripts目录中,文件名为“GetTheFrag.js”。Prototype 有一个名为 Ajax.Updater
的方法,它接受一个元素 ID——用于放置返回的内容,以及一个 URL——用于获取内容。因此,我的代码变成了
function getAspx(url,placeHolderID){
/*{success: placeHolderID} means that the container div
will only be updated if thers is a successful response
to the XMLhttpRequest call. */
new Ajax.Updater({success:placeHolderID},url,{
evalScripts: true
});
}
为了完全理解上述代码,请阅读 Prototype 文档。
客户端部分
最后一步是在目标页面上包含 Prototype Framework(它只是一个 JavaScript 文件)和“GetTheFrag.js”文件,然后在 window.onload
事件中添加一个调用,传入源页面的 URL 和一个 <div>
标签的 ID,HTML 片段将放置在该标签中。所有这些大约是页面 head
标签中的 7 行代码。
<script type="text/javascript" src="../Scripts/Prototype.js"></script>
<script type="text/javascript" src="../Scripts/GetThePage.js"></script>
<script type="text/javascript">
window.onload=function(){
getAspx('http://TheDomain/TheSourcePage.aspx','TheContainerDiv');
}
</script>
解决方案
我的目标网站的结构现在看起来像这样
Root
FolderOne (A Content Folder)
TargetPageOne.html
FolderTwo (Another Content Folder)
TargetPageTwo.html
Frags (Source Pages)
SourcePageOne.html
SourcePageTwo.html
Online (ASP.netProject)
FragmentPageOne.aspx
FragmentPageTwo.aspx
(Rest of project files)
Scripts (theScripts repository)
Prototype.js (the framework)
GetTheFrag.js
我导入了来自我另一个域的源页面,具有我新的、最小化的 AJAX 代码的目标页面,一个 ASP.NET 项目,以及两个 JavaScript 文件——Prototype Framework 和我的小型 GetTheFrag 文件。(为简洁起见,我省略了其他脚本页面和 CSS 文件等)。
关注点
您会注意到源文件位于 ASP.NET 项目之外。ASP.NET 可以很好地处理项目外部文件夹中的文件。只需正确设置虚拟路径即可。在我的情况下,它只是一个简单的 ../。为了简化起见,我将它们全部放在一个名为“Frags”的目录中。
我无法提供工作版源站或目标站点的链接,因为它们目前仅存在于我们的开发服务器上,尚未上线。上线后,我会回来更新本文的链接。
Prototype 是由 Sam Stephenson 和 Prototype 核心团队开发的开源 JavaScript AJAX 框架。Prototype AJAX 框架可从 http://www.prototypejs.org/ 获取。
免责声明
我与 Prototype 核心团队没有任何关联。我不认识团队中的任何人,甚至不认识认识团队中任何人的任何人。