PageRequestManagerParserErrorException - 带自定义Page.Render的UpdatePanel

时间:2017-10-28 23:04:12

标签: asp.net .net webforms asp.net-ajax updatepanel

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

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

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

<p>{CarMake}</p>

然后,已加载页面的呈现HTML包含:

<p>Ford</p>

然后,当UpdatePanel执行Partial PostBack时,我得到了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,但这没有效果。

1 个答案:

答案 0 :(得分:1)

我猜您的替换模板{something}位于服务器端控件内,如<asp:Literal runat="server">{something}</asp:Literal>。生命周期中的aspx页面经历了许多阶段,render非常接近结束。在运行render之前,页面会保存ViewState,以保留所有控件的状态(内容),服务器控件内容中的任何更改都会导致post ed请求不匹配并保存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);
        }
    }
}