2017-04-13 60 views
2

default2.aspx主題+動態控件創建+隱形UserControl =查看狀態錯誤?

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

同時添加樣式表藍的主題。

Also add a stylesheet to the Blue theme.

頁成功打開,但一旦我按一下按鈕,它會拋出異常

無法加載視圖狀態。視圖狀態爲 的控制樹必須與前一個請求期間用於保存視圖狀態的控制樹相匹配。例如,動態添加 控件時,在回發期間添加的控件必須匹配 在初始 請求期間添加的控件的類型和位置。

誰能解釋爲什麼這個錯誤發生?

+1

這是將viewstate(默認啓用)與動態控件(controls.Addxxx)組合在一起時得到的經典錯誤:https://blogs.msdn.microsoft.com/asiatech/2011/10/25/why-我們得到異常失敗加載視圖狀態/(主題=藍色動態添加控件,Visible = true添加信息到視圖狀態等)。 –

+0

@SimonMourier錯誤只發生在三個因素存在時。你能解釋爲什麼當我刪除三個因素中的任何一個時,錯誤不會發生? – Gqqnbig

回答

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. 圖標(靜態)
  3. 的ScriptManager(初始化)
  4. 主題(初始化,覆蓋後)
  5. 動態控制(初始化後,在這種情況下)

ASP.NET ViewState引擎是樹型串行器/解串器。樹中的每個節點都有它的ID,加上由其父母的ID和自己的ID組成的「完整ID」。當然,只要您在序列化和反序列化之間更改ID,所有投注都將關閉,引擎將檢測到它並引發'無法加載ViewState'錯誤。

所以,如果你把Visible=false,你會使用ViewState。如果你刪除它,你不會。當你自己不使用ViewState時,獲取'無法加載viewstate'錯誤的機會較少,但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,你沒有注意到你的代碼存在問題)。

1

這是由於ViewState的性質。簡單地說,當你的頁面被髮布回控制索引時,ViewState所恢復的控件就會被匹配,所以當索引改變時會導致這個問題。 在這種情況下,設置屬性這樣ViewStateMode="Disabled"爲您的網頁或改變順序添加動態元素Page.Header.Controls.AddAt(Page.Header.Controls.Count, scriptControl),它可以讓你不會恢復元素的順序干擾,可以幫助你應付的麻煩。至少,它適合我。

+0

你能解釋初始加載和回發之間的控制樹差異嗎?爲什麼如果我不動態添加ScriptManager而僅保留其他代碼,則不會發生錯誤? – Gqqnbig

+1

1.最初,您的ViewState是空的,保存到ViewState的過程在渲染後發生,當您已經添加了所有動態控件時。在回發期間,來自ViewState的加載控件在呈現自身之前發生,這意味着動態控件尚未添加。這是違反命令的原因。以下是有關頁面生命週期順序的更多信息:https://msdn.microsoft.com/en-us/library/ms972976.aspx –

+1

2.另一方面,您始終不會收到此錯誤,因爲從ViewState加載時,只有元素的順序很重要,但不是它們的類型。這意味着,有時候,儘管有另一個命令,但你可能不會遇到這個問題,因爲預期的元素被替換爲類似的元素。但是當元素完全不同時,會導致這個錯誤。這裏有更多關於這個過程的一些相關的例子:http://geekswithblogs.net/FrostRed/archive/2007/02/17/106547.aspx –