C# 主题+;动态控件创建+;不可见的UserControl=视图状态错误?
default2.aspxC# 主题+;动态控件创建+;不可见的UserControl=视图状态错误?,c#,asp.net,viewstate,C#,Asp.net,Viewstate,default2.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(ob
<%@ 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>
私有无效页面\u预呈现(对象发送方,System.EventArgs e)
{
HtmlGenericControl scriptControl=新的HtmlGenericControl(“脚本”);
Page.Header.Controls.AddAt(0,scriptControl);//如果注释掉此行,则不会发生异常。
}
私有无效页_Init(对象发送方,System.EventArgs e)
{
ScriptManager oSM=新建ScriptManager();
Page.Form.Controls.Add(oSM);//如果这一行被注释掉,则不会发生异常。
}
页面成功打开,但一旦我单击按钮,它就会抛出异常
未能加载viewstate。viewstate所在的控件树
正在加载的控件必须与用于保存的控件树匹配
上一个请求期间的viewstate。例如,在添加
控件,回发期间添加的控件必须匹配
初始过程中添加的控件的类型和位置
请求
有人能解释为什么会发生此错误吗?这是由于ViewState的性质造成的。简单地说,当您的页面被发回时,ViewState还原到的控件与控件索引匹配,因此当索引更改时会导致此问题。
在这种情况下,以这种方式为页面设置属性ViewStateMode=“Disabled”
,或者更改添加动态元素的顺序page.Header.Controls.AddAt(page.Header.Controls.Count,scriptControl)
,可以帮助您解决问题。至少,这对我来说是可行的。要调试这些错误,我强烈建议启用跟踪(Trace=“true”在@page指令中,或者使用a),以便您可以查看服务器的控制树
在GET上,控制树如下所示(注意自动生成的唯一ID):
HtmlHead
+ctl05:HtmlGenericControl(来自预渲染代码)
+ctl01:标题(标签)
+ctl02:FavIcon(您的FavIcon.ascx)
+ctl04:HTMLINK(来自“蓝色”主题)
HtmlForm
+ctl03:脚本管理器
“加载ViewState失败”错误的根本原因是:
- 您可以使用ViewState。这是一个在许多情况下都可以禁用的选项
- 您不使用固定ID(这就是为什么VisualStudio的IDE总是向控件添加自动但固定的ID)
- 当更改头部的控制树时,可以在树中后期动态添加控制。另外,您可以在其他人之前添加它(AddAt)
生成的ID遵循ASP.NET的:
标题(静态)
法维康(静态)
脚本管理器(初始化)
主题(初始化,重写后)
动态控件(在本例中,在Init之后)
ASP.NET ViewState引擎是一个树序列化程序/反序列化程序。树中的每个节点都有自己的ID,再加上由其父节点ID和自己的ID组成的“完整ID”。当然,只要在序列化和反序列化之间更改ID,所有赌注都将关闭,引擎将检测到它并引发“加载ViewState失败”错误
因此,如果您将Visible=false
,您将使用ViewState。如果你移除它,你就不会。当您自己不使用ViewState时,出现“加载ViewState失败”错误的可能性较小,但ASP.NET可以在您使用其所有功能(主题等)时代表您使用某些ViewState。在可见的情况下,它只意味着控件在那里(并使用ViewState),但没有渲染(其渲染大小为0)。但是您会看到使用ViewState的任何其他属性的问题,它不是Visible属性特有的(您也可以尝试this.ViewState[“test”]=“which”
)
如果您将
放在页面的其他位置,它也会起作用,因为它不再位于Head控件树中,并且不会干扰主题的链接或您的动态控件
对于Theme和ScriptManager,只是当您使用它们时,它会更改或不更改ID,而系统可能会检测到它
打破ViewState的方法有无数种。真正困难的是,它似乎在不应该的情况下工作(例如,只要您不使用FavIcon的ViewState,您就不会注意到代码存在问题)。这是将ViewState(默认情况下启用)与动态控件(controls.Addxxx)相结合时出现的典型错误:(theme=blue动态添加控件,Visible=true向viewstate添加信息,等等).@SimonMourier只有在这三个因素存在时才会发生错误。你能解释一下为什么在我删除这三个因素中的任何一个时都不会发生错误吗?你能解释一下初始加载和回发之间的控制树差异吗?如果我不动态添加ScriptManager,而不添加其他代码,为什么不会发生错误?1.我首先,您的ViewState为空,保存到ViewState的过程在渲染后进行,此时您已经添加了所有的动态控件。在从ViewState回发加载控件的过程中,控件是在渲染本身之前进行的,这意味着动态控件尚未添加。这打破了顺序。下面介绍有关t页面生命周期的顺序:2.另一方面,您不会一直犯这种错误,因为从ViewState加载时,只有元素的顺序才重要,而不是它们的类型。这意味着,有时,尽管顺序不同,您可能不会遇到此问题,因为预期的元素被类似的元素替换。但是,当元素完全不同时,会导致此错误。下面通过一些相关示例详细介绍此过程:我只在控件开头添加了主题、scriptControl和FavIcon元素(Visible=false)的同时遇到此问题。FavIcon元素的索引是2(添加后的第三个控件)
<%@ 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>
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