2017-10-28 188 views
0

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

自定义的Page.Render与Response Filter基本相同,我已经阅读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,但没有效果。

+0

如果响应包含正确替换的文本,您是否需要执行sb.Replace? – wazz

+0

@wazz sb.Replace是什么在做文本替换。在sb.Replace调用之前,呈现的HTML输出仍然包含{CarMake} – emkayultra

+0

啊。它包含正确替换的文本,但在代码运行后。 :\ – wazz

回答

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); 
     } 
    } 
} 
+0

这个信息真的很有用 - 我不知道SaveViewState在Render之前被调用。然而,我仍然处于亏损状态:你究竟在Page_PreRenderComplete中修改了什么?我挖掘了Page的源代码,并没有看到我可以可靠地用来引用Page的HTML输出的属性。除非你直接操纵Page.Controls? – emkayultra

+0

@emkayultra请参阅更新。 ;) –

+0

我想这将会是你说的,而这正是我最终做的。我对导航Page的控制层次结构与后处理呈现的HTML字符串的性能有点担心,但这是必须要做的。谢谢! – emkayultra

相关问题