ASP 页面上的服务器端动态包含






2.67/5 (5投票s)
2003年10月28日
4分钟阅读

92991

690
用于 ASP 页面上服务器端动态包含的 COM 对象
引言
此组件旨在解决我在构建网站时遇到的一个问题。在构建网站的某个阶段,我意识到我有很多页面(不断增长),它们具有相同的格式,并且内容几乎相同,除了某些主要在 HTML 代码方面有所不同的部分。网站的规模越来越大,而只有少数页面部分不同。因此,我一直在寻找一种方法来尽可能减小网站的规模,同时又不会使其难以管理。
解决方案
基本概念是创建一个 asp 页面,该页面将包含页面的公共部分,并动态地包含我将提供的其他子页面。
我在 MSDN 上进行了一些搜索,并找到了神奇的服务器端 #include 语句,该语句允许在一个网页中包含另一个子页面。在第一次尝试中,我硬编码了文件名,并很高兴看到它工作了。但是,当我尝试使用变量或参数而不是硬编码文件名时,我只收到“HTTP 500 - 内部服务器错误”。
在多次尝试此技术失败后,另一种想法是采取相反的路径,并将所有子页面更改为 asp 页面,并再次使用服务器端包含来添加所有其他公共内容。我知道这会起作用,并且也会大大减小网站的规模,但会给我带来另一个大问题。首先是需要完成的工作太多,其次是会随着页面数量的增加而使网站的复杂性增加,从而使其更难以管理。如果我稍后想将子页面移动到不同的子目录中,并根据某些关键字对它们进行分类,则我将不得不编辑许多文件的链接。用户不会注意到更改,但困难的部分将在于我。
另一种想法是创建一个数据库,将子页面内容存储在其中,然后使用记录集来包含我想要的记录文本。创建数据库、添加一些示例页面并进行测试很容易。尽管这很成功,但更新页面内容很困难,并且维护网站以进行更改的效率很低。我必须获取记录数据,将其存储在文件中,进行任何更改,然后将内容存储回表中。如果子页面没有更改,那可能很好,但我想获得更灵活、更快、更轻松的东西。
因此,我决定实现类似于我自己的服务器端包含内容,并能够
- 拥有动态包含以保持网站的规模较小。
- 避免在子页面中复制公共部分。
- 将子页面保留在文本/html 文件中,以受益于现有的 Web 创作工具。
- 将所有链接仅保留在所需位置。
- 不需要数据库和/或数据库工具来查看/编辑页面内容。
- 使维护过程尽可能快且简单。
- 不需要学习任何新东西,只需在现有的 asp 页面中添加几行代码即可。
使用 COM 对象
要使用此 COM 对象,您必须将 dll 复制到 Web 服务器的某个位置(例如 C:\Inetpub),并使用 regsvr32 注册它(例如 regsvr32 C:\Inetpub\SSDI.dll)。
然后将目录 IIS Files 的文件复制到 Web 服务器上 Web 站点根目录下的目录中。现在,您可以通过在 Internet Explorer 地址栏中键入 https:///master.asp?file=subPageFilename 来进行测试。(subPageFilename 可以是 test1.html 或 test2.html。如果未提供参数,它将默认为 test1.html)。
代码解释
asp 页面创建一个 SSDI.Util
的实例
<%
...
var x=Server.CreateObject("SSDI.Util");
%>
并调用 Include 成员函数。
<%=x.Include(Server.MapPath(szFile))%>
完整的 asp 页面代码
<%@language="javascript"%>
<HTML>
<%
var szFile = String(Request.QueryString("file"));
if ((szFile == "undefined") || (szFile == ""))
szFile = "test1.html";
var x = Server.CreateObject("SSDI.Util");
%>
<BODY>
<P>We are about to include file: <%=szFile%></P>
<%=x.Include(Server.MapPath(szFile))%>
</BODY>
</HTML>
COM 对象本身是一个简单的 COM 对象,它导出一个简单的接口 IUtil
,其中包含一个属性 Include
。此属性的代码将打开文件,将其读入已分配的缓冲区,将缓冲区内容转换为 BSTR
,并将其返回以供脚本语言使用,从而释放该文件。
STDMETHODIMP CUtil::get_Include(BSTR filename, BSTR *pVal)
{
CString szFilename = filename;
DWORD cbRead = 0;
//Open the file
HANDLE hFile = ::CreateFile( szFilename, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if ( hFile == INVALID_HANDLE_VALUE )
{
pVal = NULL;
return S_FALSE;
}
//Get file size and allocate enough buffer to read it.
DWORD cbFile = ::GetFileSize( hFile, NULL );
if ( cbFile == (DWORD) -1 )
{
CloseHandle( hFile );
return S_FALSE;
}
char *pszFileContent = (char *)LocalAlloc( LPTR, cbFile + 1 );
if ( !pszFileContent )
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
CloseHandle( hFile );
return S_FALSE;
}
if ( !::ReadFile( hFile, pszFileContent, cbFile, &cbRead, NULL ))
{
CloseHandle( hFile );
LocalFree( pszFileContent );
return S_FALSE;
}
pszFileContent[cbRead] = '\0';
//Convert buffer data to BSTR and return it for script use
CString szFileContents = pszFileContent;
*pVal = szFileContents.AllocSysString();
CloseHandle( hFile );
LocalFree( pszFileContent );
return S_OK;
}
重新构建演示
此演示使用 (WTL 7.0) CString
来处理字符串。可以从 Microsoft 网站 下载 WTL 7.0。