c# - 主题 + 动态控件创建 + 不可见的 UserControl = View 状态错误?

标签 c# asp.net viewstate

默认2.aspx

<%@ 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>

FavIcon.ascx

<%@ Control Language="C#" ClassName="FavIcon" AutoEventWireup="true" %>

<script runat="server">

    void Page_Load(object sender, EventArgs e)
    {
        this.Visible = false;//If this line is commented out, no exception will occur.
    }

</script>

还向 Blue 主题添加样式表。

Also add a stylesheet to the Blue theme.

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

Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

谁能解释一下为什么会发生这个错误?

最佳答案

要调试这些错误,我强烈建议启用跟踪(@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. 脚本管理器(初始化)
  4. 主题(初始化,覆盖后)
  5. 动态控件(在本例中是在初始化之后)

ASP.NET ViewState 引擎是一个树序列化器/反序列化器。树中的每个节点都有自己的 ID,以及由其父节点 ID 和自己的 ID 组成的“完整 ID”。当然,一旦您在序列化和反序列化之间更改 ID,所有的赌注都会消失,引擎会检测到它并引发“无法加载 ViewState”错误。

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

如果你输入<uc1:favicon runat="server"></uc1:favicon>在页面的其他地方,它也将起作用,因为它不再位于 Head 控件树中,并且不会干扰主题的链接或动态控件。

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

破坏 ViewState 的方法有无数种。真正困难的是,它在不应该工作的时候可能看起来可以工作(例如,只要您不使用 FavIcon 的 ViewState,您就不会注意到代码有问题)。

关于c# - 主题 + 动态控件创建 + 不可见的 UserControl = View 状态错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43402291/

相关文章:

c# - 在 C# 中的 UploadedFile 上使用 BinaryReader 的空数组

asp.net - 长时间运行的 HttpWebRequest

c# - asp.net如何打开新标签页

javascript - 跨不同页面保留大约 1KB 的数据

iOS MVVM 处理初始 View 状态

c# - 在线程中发出和处理异步 Web 服务请求

c# - RSA C# 加密 Java 解密

c# - 绑定(bind) List<Dictionary<string,string>> 到 DropDownList

c# - 动态用户控件在回发后获取并维护值

asp.net - System.Web.UI.ViewStateException ,无效的 View 状态