2

我继承了 System.Web.UI.HtmlTextWriter 在 ASP.NET 应用程序中对 HTML 进行一些自定义呈现。这是在我的 Web.config 文件中使用以下配置的:

<browserCaps>
  tagwriter="MyAssembly.CustomHtmlTextWriter, MyAssembly"
</browserCaps>

这适用于常规页面请求,调用 OnTagRender 等重写方法并将自定义 HTML 发送到浏览器。

但是,当使用 UpdatePanel 进行异步回发时,永远不会调用此代码,并且 HTML 在没有我的自定义修改的情况下到达浏览器。我是否缺少一些将为 AJAX 请求加载自定义 HtmlTextWriter 的配置?

4

1 回答 1

3

首先,我可以向您保证您的自定义 HTMLTextWriter 被正确调用,并且您在配置中没有做错任何事情。

使用您的 web.config 部分,我编写了一个测试应用程序,并在该行包含以下断点var cap = ...

    protected void UpdatePanel1_Load(object sender, EventArgs e)
    {
        var cap = Request.Browser.TagWriter;
    }

在初始 HTTP GET 和 AJAX 回发中,断点被命中,我可以看到所使用的 TagWriter 实际上是 CustomHtmlTextWriter。另外,我可以在 CustomHtmlTextWriter 构造函数上设置一个断点,并且这个断点在回发时被命中。

我还确认,即使您在回发中添加了一个全新的控件,即使调用了 CustomHtmlTextWriter 构造函数,OnTagRender、OnAttributeRender 和其他事件也不会触发。

此外,不会调用 RenderBefore...() 和 RenderAfter...() 方法。

所以这回答了你的问题“我在我的配置中做错了什么吗?”:不,你没有。您的自定义 HtmlTextWriter 被实例化和引用,但没有调用任何有用的方法(调用了 BeginRender,但没有调用通常用于更改标签的方法)。

在这一点上,值得注意的是 browserCaps 标记在 .NET 2.0 中已被弃用,因此您的用例似乎不受支持也许并不奇怪。根据您到底要做什么,我认为 ControlAdapter 架构应该可以完成工作。

例如,假设我想将所有 TextBoxes 和 Labels 替换为仅包含其 ID 的跨度,并在初始 GET 和 AJAX 回发上进行这项工作。当然,您的示例会更复杂,但希望这种简化会给您带来想法。

我需要做的就是创建一个可以作用于任何 Web 控件的 ControlAdapter:

public class CustomControlAdapter : WebControlAdapter
{
    protected override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.WriteLine();
        writer.WriteBeginTag("span");
        writer.Write(HtmlTextWriter.TagRightChar);
    }

    protected override void RenderEndTag(HtmlTextWriter writer)
    {
        writer.WriteEndTag("/span");
        writer.WriteLine();
    }

    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.WriteLine(Control.ID);
    }
}

然后,我将它连接到我感兴趣的控件类型。为此,我在 App_Browsers 文件夹中创建了一个 Adapters.browser 文件,并包含以下配置:

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter
        controlType="System.Web.UI.WebControls.Label"
        adapterType="WebApplication1.CustomControlAdapter"
      />
      <adapter
        controlType="System.Web.UI.WebControls.TextBox"
        adapterType="WebApplication1.CustomControlAdapter"
      />
    </controlAdapters>
  </browser>
</browsers>

请注意,我的“默认”浏览器 refID 将在所有浏览器上运行。现在,当需要呈现 Label 或 TextBox Web 控件时,CustomControlAdapter 会处理它。上面的代码在我的示例应用程序中进行了测试,即使使用 AJAX 也能完美运行。在您的情况下,我猜您只需要在上面的 Adapters.browser 文件中添加更多控件类型,您就应该 100% 投入业务。

于 2013-02-08T20:11:38.473 回答