使用主页和 HTTP 模块进行内容包装
使用母版页和 IHttpModule 包装静态内容。
引言
最近,我有一个客户正在重新设计一个包含数百个静态文件和几个动态内容部分的网站。他们询问了我有关如何使此网站可维护的选项,而无需编写、购买或安装 CMS(内容管理系统 - 如 DotNetNuke)工具。我最初建议他们创建一个母版页,然后将所有静态页面的内容移到使用母版页的单个 .aspx 页面中。他们没有多少 ASP.NET 技能,所以这对他们来说有点不具吸引力。他们喜欢母版页的概念;但是,他们更喜欢直接编辑静态 HTML 文件,并将新布局放入文件中。
在我看来,这似乎是一个糟糕的解决方案,因为将来每次重新设计网站时,仍然需要手动编辑数百个文件。我推荐了另一种解决方案。创建一个 IHttpModule
,该模块检查请求是否为有效页面。如果是,则通过。如果不是,则检查请求的 URL 是否存在“内容”文件。如果存在,则将请求传递给一个了解如何读取该“内容”文件并将其内容放入母版页布局的页面。
本文描述了这种架构的一个非常简单的实现。
背景
您可能想阅读有关
Using the Code
假设我们的网站有以下文件
/index.html
/articles/Article1.html
/articles/Article2.html
并且我们希望它们都具有相同的布局。我们可以创建一个母版页,并让项目看起来像这样
/default.aspx
/Site.Master
/articles/Article1.aspx
/articles/Article2.aspx
但这并非一个易于扩展的模型,因为您将不得不为每个页面创建一个新的 .aspx 页面。
我建议您创建一个母版页,并将静态页面中的内容提取到 .con 文件(或您喜欢的任何扩展名)中。然后,项目布局将如下所示
/default.aspx
/wrapperform.aspx
/Site.Master
/articles/Article1.con
/articles/Article2.con
WrapperForm.aspx 是一个使用母版页的网页,它知道如何读取 .con 文件并将其推送到其 Content
控件中。
还需要另外两件事。
首先是能够读取 .con 文件并将其写入响应的控件(WrapperForm.aspx 无法做到这一点,因为它无法专门在 Content
控件中写入)。此控件放置在 WrapperForm.aspx 的 Content
控件中。
Wrapper
(扩展 WebControl
)具有此 RenderContent
方法
// Get the path of the query string
string path = Context.Request["path"];
if ( !string.IsNullOrEmpty(path))
{
// read it in
using( FileStream stream = File.OpenRead( Context.Server.MapPath( path )) )
{
byte[] b = new byte[1024];
ASCIIEncoding encoding = new ASCIIEncoding();
while ( stream.Read( b, 0, b.Length ) > 0 )
{
// write it out
output.Write(encoding.GetString(b));
}
}
}
它只是从文件系统中获取 .con 文件并将其写入响应。
其次,我们需要一种方法让 IIS 为实际上不存在的页面命中我们的 WrapperForm.aspx。我们将使用 IHttpModule
来实现。
RequestHandler
侦听每个请求,如果找不到请求的物理文件,它会查找相应的 .con 文件。如果内容文件存在,则将请求传递到 WrapperForm.aspx 页面。完成此壮举的代码块是
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
// Have we requested a file that exists?
if ( !File.Exists( context.Server.MapPath( context.Request.FilePath ) ) )
{
// Check for a content file on the same path
string path = Path.ChangeExtension( context.Request.FilePath, ".con" );
if (File.Exists(context.Server.MapPath(path)))
{
// Forward to our wrapper
context.Server.Transfer( "~/WrapperForm.aspx?path=" + path, true );
}
}
下一个问题是非 ASP.NET 处理的扩展。IIS 不会将请求传递到 .NET 代码。这意味着,如果我们希望处理所有 .html 文件,它们将永远不会到达我们的 RequestHandler
,因为 IIS 正在监视 .html 文件并返回 404。您可以选择将虚假 URL 设置为 .aspx 页面,或者更改应用程序的文档映射,将 .html(或其他)页面路由到 ASP.NET(这在托管环境中可能很困难)。
结果
在包含的源中,您将找到以下内容结构
/default.aspx
/WrapperForm.aspx
/test.con
/dir/junk.con
使用此解决方案,我可以浏览到
- default.aspx 并命中默认页面
- test.html(和 test.aspx)并将 test.con 数据以正确的布局重现
- dir/junk.html(和 junk.aspx)并将 junk.con 数据以正确的布局重现
关注点
这不是一个特别的解决方案。它非常基础,而且实际上似乎只解决了一个问题,即“皮肤化”静态内容。此解决方案确实增加了相当大的价值。
- 内容可以轻松迁移到数据库(只需将
Wrapper
控件更改为从数据库而不是文件系统获取内容) - 旧的、现有的、深度链接仍然有效
- 搜索引擎链接得以维护
如果我要为客户实施此方案,我会让内容文件包含更多内容。我会让它们成为 XML,包含页面标题(此方案默认使用文件标题)、一些 SEO 元内容和面包屑导航信息,所有这些都是 CMS 会提供的内容。
历史
暂无更新。