PageRequestManagerParserErrorException - 具有自定义 Page.Render 的 UpdatePanel

PageRequestManagerParserErrorException - UpdatePanel with custom Page.Render

我需要能够在每个页面上进行动态的客户特定文本替换。例如,我可以将“{CarMake}”放在页面的任何位置,它会将“{CarMake}”更改为我们福特客户的 "Ford",丰田客户的 "Toyota",等等。我们正在做这是一个自定义 Page.Render 函数,它将在输出到客户端之前对呈现的 html 进行替换。

自定义 Page.Render 与响应过滤器本质上是相同的想法,我已经阅读了 Eilon Lipton's fantastic explanation of this error,但我仍然对为什么在我的特定情况下这是一个问题感到困惑。

.ASPX 页面标记在 UpdatePanel 中包含:

<p>{CarMake}</p>

然后加载页面的渲染HTML包含:

<p>Ford</p>

然后,当 UpdatePanel 执行部分回发时,我收到上述 UpdatePanel 响应的解析错误,它似乎包含正确替换的文本(就像 HTML 的初始呈现):

"1|#||4|2325|updatePanel|UpdatePanelCars|...<p>Ford</p>..."

那么,如果呈现的 HTML 完全相同,为什么会出现问题?客户端如何解析甚至检测到差异?

供参考,进行替换的代码是这样的:

class TemplatedPage: System.Web.UI.Page
{
   ...
   protected override void Render(HtmlTextWriter writer)
   {
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);

        HtmlTextWriter hWriter = new HtmlTextWriter(sw);
        base.Render(hWriter); //obtain full html markup, still containing {} at this point

        sb.Replace("{CarMake}", "Ford");
        //other Replacements...

        string alteredPageContents = sb.ToString();

        writer.Write(alteredPageContents);
   }
}

我试过将 EnableEventValidation 设置为 false,但没有任何效果。

我想您的替换模板 {something} 在服务器端控件内,例如 <asp:Literal runat="server">{something}</asp:Literal>。一个 aspx 页面在其生命周期中会经历许多阶段,render 已经非常接近尾声了。在 运行 render 之前,页面保存 ViewState,这会保留所有控件的状态(内容),服务器控件内容的任何更改都会导致 posted 请求与保存 ViewState.
您可以修改页面内容的最新时刻是 page_PreRenderComplete 事件处理程序。
当然,如果页面没有 post 返回(全部或部分),那也没关系。
事实上,我在许多(所有)页面中使用了非常相似的代码,但我只对控件渲染进行了重新排序(将 script 放在底部等等)。 render 内的替换导致错误,我在 Page_PreRenderComplete.

内使用了一些解决方法

更新回复评论

Page_PreRenderComplete中你可以处理页面树来进行替换。像这样:

void Page_PreRenderComplete(object sender,EventArgs e)
{
    ProcessPageTree((Control)sender); //sender is Page which inherit from Control
}
void ProcessPageTree(Control control) //All server side controls inherit from abstract Control
{
    if(control is HyperLink)
    {
        var hl = control as HyperLink;
        hl.Text = hl.Text.Replace("{{something}}", "something new");
    }
    else if(control is Literal)
    {
        var ltr = control as Literal;
        ltr.Text = ltr.Text.Replace("{{some}}", "something another");
    }
    if (control.HasControls())
    {
        foreach(Control c in control.Controls)
        {
            ProcessPageTree(c);
        }
    }
}