- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在构建一个相当简单的 CMS。我需要拦截对我的 Web 应用程序中大多数 .aspx 页面的请求,以便完全控制输出。在大多数情况下,输出将从缓存中提取,并且只是纯 HTML。
但是,仍然有几个页面需要使用 asp: 控件。我认为绕过一些特定请求的最佳方法是继承 System.Web.UI.PageHandlerFactory 并在需要时调用 MyBase 实现(如果我在这里错了,请纠正我)。但是如何将所有其他请求转移到我的自定义处理程序?
最佳答案
当我编写一个简单的 CMS 时,我很难使用 PageHandlerFactory 让它做我想做的事。最后我切换到了 IHttpModule。
我的模块将首先检查请求的路径中是否有 .aspx 文件。如果页面上有用户控件或由于某种原因不适合 CMS,我只会这样做。因此,如果文件存在,它将从模块中返回。之后,它会查看请求的路径并将其压缩为“导航标签”。因此 ~/aboutus/default.aspx 将变为 page.aspx?nt=aboutusdefault。 page.aspx 将从 CMS 加载正确的内容。当然,重定向发生在服务器端,因此用户/蜘蛛永远不会知道发生了什么不同的事情。
using System;
using System.Data;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
namespace MyCMS.Handlers {
/// <summary>
/// Checks to see if we should display a virutal page to replace the current request.
/// Code adapted from:
/// Rewrite.NET -- A URL Rewriting Engine for .NET
/// By Robert Chartier
/// http://www.15seconds.com/issue/030522.htm
/// </summary>
public class VirtualPageModule : IHttpModule {
/// <summary>
/// Init is required from the IHttpModule interface
/// </summary>
/// <param name="Appl"></param>
public void Init(System.Web.HttpApplication Appl) {
// make sure to wire up to BeginRequest
Appl.BeginRequest += new System.EventHandler(Rewrite_BeginRequest);
}
/// <summary>
/// Dispose is required from the IHttpModule interface
/// </summary>
public void Dispose() {
// make sure you clean up after yourself
}
/// <summary>
/// To handle the starting of the incoming request
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
public void Rewrite_BeginRequest(object sender, System.EventArgs args) {
// Cast the sender to an HttpApplication object
HttpApplication httpApp = (HttpApplication)sender;
// See if the requested file already exists
if (System.IO.File.Exists(httpApp.Request.PhysicalPath)) {
// Do nothing, process the request as usual
return;
}
string requestPath = VirtualPathUtility.ToAppRelative(httpApp.Request.Path);
// Organic navigation tag (~/aboutus/default.aspx = nt "aboutusdefault")
Regex regex = new Regex("[~/\\!@#$%^&*()+=-]");
requestPath = regex.Replace(requestPath, string.Empty).Replace(".aspx", string.Empty);
string pageName = "~/page.aspx";
string destinationUrl = VirtualPathUtility.ToAbsolute(pageName) + "?nt=" + requestPath;
SendToNewUrl(destinationUrl, httpApp);
}
public void SendToNewUrl(string url, HttpApplication httpApp) {
applyTrailingSlashHack(httpApp);
httpApp.Context.RewritePath(
url,
false // RebaseClientPath must be false for ~/ to continue working in subdirectories.
);
}
/// <summary>
/// Applies the trailing slash hack. To circumvent an ASP.NET bug related to dynamically
/// generated virtual directories ending in a trailing slash (/).
/// As described by BuddyDvd:
/// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105061
/// </summary>
/// <param name="httpApp">The HttpApplication.</param>
/// <remarks>
/// Execute this function before calling RewritePath.
/// </remarks>
private void applyTrailingSlashHack(HttpApplication httpApp) {
if (httpApp.Request.Url.AbsoluteUri.EndsWith("/") && !httpApp.Request.Url.AbsolutePath.Equals("/")) {
Type requestType = httpApp.Context.Request.GetType();
object clientFilePath = requestType.InvokeMember("ClientFilePath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty, null, httpApp.Context.Request, null);
string virtualPathString = (string)clientFilePath.GetType().InvokeMember("_virtualPath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, clientFilePath, null);
clientFilePath.GetType().InvokeMember("_virtualPath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, clientFilePath, new object[] { virtualPathString });
requestType.InvokeMember("_clientFilePath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, HttpContext.Current.Request, new object[] { clientFilePath });
object clientBaseDir = requestType.InvokeMember("ClientBaseDir", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty, null, httpApp.Context.Request, null);
clientBaseDir.GetType().InvokeMember("_virtualPath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, clientBaseDir, new object[] { virtualPathString });
requestType.InvokeMember("_clientBaseDir", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, HttpContext.Current.Request, new object[] { clientBaseDir });
}
}
}
}
关于asp.net - .aspx 的自定义 PageHandlerFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/425512/
使用 Microsoft.Web.Infrastructure 程序集,我们可以在预应用程序启动阶段注册模块,如下所示: DynamicModuleUtility.RegisterModule(typ
我正在构建一个相当简单的 CMS。我需要拦截对我的 Web 应用程序中大多数 .aspx 页面的请求,以便完全控制输出。在大多数情况下,输出将从缓存中提取,并且只是纯 HTML。 但是,仍然有几个页面
我在 32 位机器经典应用程序池中收到以下错误 Handler "PageHandlerFactory-ISAPI-4.0_32bit" has a bad module "IsapiMod
使用 IIS7.5,该网站在 Visual Studio 中运行良好,但是当我尝试在 IIS 上部署时出现以下错误。 Module IIS Web Core Notification ExecuteR
我正在配置 MVC 3 项目以在 IIS 的本地安装上运行,并遇到以下 500 错误: Handler "PageHandlerFactory-Integrated" has a bad module
所以我有一个旧的网络表单站点,并且正在努力使其更易于维护。把它扔掉并重写它不是一种选择。 IoC 显然是它首先得到的东西之一,但这给我留下了服务定位器模式和糟糕的品味,并且想知道它是否可以做得更好。
我是一名优秀的程序员,十分优秀!