这是我猜的“主要问题”:
是否有一种“.NET 方式”可以很早就收到请求(通过 HttpHandler 或 HttpModule)并以标准控件或用户/自定义控件的形式注入标准 asp.net 标记,并让框架处理它就像一个动态编译的页面?
更多背景
好的,所以我们使用的这个自定义 CMS 可以很好地构建相当复杂的网站。它有一个很好的模板系统、用户权限、易于安装等。但是,我们想要添加的一个功能是能够添加动态内容。
在 CMS 退出并执行“它的事情”之后,结果本质上是一个巨大的 HTML 字符串,它在响应中被发回。渲染引擎包含在处理这种“cms 东西”的类中。现在这发生在标准页面生命周期中,但没有理由不能独立调用它。
我已经能够接近 httpHandler 和 httpModule,但问题是我真正需要的是获取“cms html 字符串”,添加我自己的 .net 控件,然后让框架采用新的字符串并从中构建控制树(以及视图状态等)。
我得到的最接近的是 HttpModule,它在 PreRequestHandlerExecute 期间将过滤器附加到响应。这个过滤器只是寻找用标签标记替换 {{replaceme}} 的地方(作为概念证明......下面的示例)。我认为这会起作用,因为从我所阅读的内容来看,这是在创建控制树之前,但所发生的只是将 asp.net 标记写入页面(不是由 .NET 呈现)。
我尝试过的另一件事是通过 HttpHandler 完全控制。这几乎同样有效(也是下面的示例)......这里的问题是,虽然我可以构建自己的控件树,甚至执行 ascx 控件,但没有地方可以将所有这些东西合并在一起(记住我已经有一个完整的 html 文档字符串,我试图在运行时合并它并将其传递给 .NET)。
我觉得我很接近但缺少一些非常简单的方法来将大部分工作传递给.NET......
Http模块
private void PreRequestHandlerExecute(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Filter = new PageFilter(context.Response.Filter);
}
过滤器(来自我认为的 SO 示例)
public override void Write(byte[] buffer, int offset, int count)
{
string strBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);
// ---------------------------------
// Wait for the closing </html> tag
// ---------------------------------
Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);
if (!eof.IsMatch(strBuffer))
{
responseHtml.Append(strBuffer);
}
else
{
responseHtml.Append(strBuffer);
string finalHtml = responseHtml.ToString();
finalHtml = finalHtml.Replace("{{replaceme}}", @"<asp:Label id=""lblMyTest"" runat=""server"" Text=""This is a label that was replaced by my responsefilter"" />");
// Transform the response and write it back out
byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml);
responseStream.Write(data, 0, data.Length);
}
}
测试 HttpHandler
public void ProcessRequest(HttpContext context)
{
MyBasePage page = new MyBasePage();
Test tpage = (Test)BuildManager.CreateInstanceFromVirtualPath("~/Test.ascx", typeof(Test));
var htmlform = new System.Web.UI.HtmlControls.HtmlForm();
var panel = new Panel();
panel.Controls.Add(new Label() { Text = "Hello World" });
panel.Controls.Add(tpage);
htmlform.Controls.Add(panel);
page.Controls.Add(htmlform);
page.ProcessRequest(context);
}