主题+动态控件创建+ Invisible UserControl =查看状态错误?

时间:2017-04-13 21:51:30

标签: c# asp.net viewstate

default2.aspx

synchronize

FavIcon.ascx

<%@ Page Language="C#" AutoEventWireup="true" Theme="Blue" %>

<%@ Register TagPrefix="uc1" TagName="favicon" Src="~/FavIcon.ascx" %>

<!DOCTYPE html>

<script runat="server">


    private void Page_PreRender(object sender, System.EventArgs e)
    {
        HtmlGenericControl scriptControl = new HtmlGenericControl("script");
        Page.Header.Controls.AddAt(0, scriptControl);//If this line is commented out, no exception will occur.
    }


    private void Page_Init(object sender, System.EventArgs e)
    {
        ScriptManager oSM = new ScriptManager();
        Page.Form.Controls.Add(oSM);//If this line is commented out, no exception will occur.
    }


</script>

<html>
<head runat="server">
    <title></title>
    <uc1:favicon runat="server"></uc1:favicon>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Button ID="Button1" runat="server" Text="Button" />
    </form>
</body>
</html>

还要在Blue主题中添加样式表。

Also add a stylesheet to the Blue theme.

页面打开成功,但是一旦我点击按钮,它就会抛出异常

  

无法加载视图状态。 viewstate所在的控制树   正在加载必须与用于保存的控制树匹配   在上一个请求期间查看状态。例如,添加时   动态控制,回发期间添加的控件必须匹配   初始期间添加的控件的类型和位置   请求。

有谁可以解释为什么会发生这种错误?

2 个答案:

答案 0 :(得分:1)

由于ViewState的性质,它发生了。简而言之,当您的页面被回发时,恢复ViewState的控件将与控件索引匹配,因此当索引更改时会导致此问题。 在这种情况下,为您的网页设置属性ViewStateMode="Disabled"或更改添加动态元素Page.Header.Controls.AddAt(Page.Header.Controls.Count, scriptControl)的顺序,这样可以避免干扰已恢复元素的顺序,可以帮助您应对麻烦。至少,它适合我。

答案 1 :(得分:1)

要调试这些错误,我强烈建议启用跟踪(@page指令中的Trace =“true”,或使用global setting in web.config),这样就可以看到服务器的控制树。

在GET上,控制树就是这样(注意自动生成的唯一ID):

  HtmlHead
    + ctl05 : HtmlGenericControl (from your PreRender code)
    + ctl01 : Title (the <title> tag)
    + ctl02 : FavIcon (your favicon.ascx)
    + ctl04 : HtmlLink (from the 'Blue' theme)

  HtmlForm
    + ctl03 : ScriptManager

“无法加载ViewState”错误的根本原因是:

  • 您使用ViewState 。在许多情况下,这是一个可以禁用的选项。
  • 您不使用固定ID (这就是为什么Visual Studio的IDE会一直为控件添加自动但固定的ID)。
  • 您在树中动态地添加控件,因为它会更改头部的控制树。另外,您可以在其他人之前添加它(AddAt)。

生成的ID遵循ASP.NET的lifecycle order

  1. 标题(静态)
  2. FavIcon(静态)
  3. ScriptManager(Init)
  4. 主题(初始化,覆盖后)
  5. 动态控件(在本例中为Init之后)
  6. ASP.NET ViewState引擎是树序列化器/反序列化器。树中的每个节点都有它的ID,以及由其父ID和自己的ID组成的“完整ID”。当然,只要您在序列化和反序列化之间更改ID,所有投注都会关闭,引擎会检测到它并引发“Failed to Load ViewState”错误。

    因此,如果你放Visible=false,你将使用ViewState。如果你删除它,你就不会。当您自己不使用ViewState时,获取“无法加载视图状态”错误的可能性较小,但是当您使用其所有功能(主题等)时,ASP.NET可以代表您使用某些ViewState。在Visible的情况下,它只意味着控件存在(并使用ViewState),但不渲染(它的渲染大小为0)。但是你会看到使用ViewState的任何其他属性的问题,它不是特定于Visible属性(你也可以尝试this.ViewState["test"] = "whatever")。

    如果您将<uc1:favicon runat="server"></uc1:favicon>放在页面的其他位置,它也会起作用,因为它不再位于Head控制树中,并且不会干扰Theme的链接或动态控件。

    对于Theme和ScriptManager,只是当你玩它们时,它会改变或不改变ID,系统可能会检测到它。

    有许多方法可以打破ViewState。什么是非常困难的,它似乎不应该工作(例如,只要你不使用FavIcon的ViewState,你没有注意到你的代码有问题。)