DCSIMG
Question from Tapuz .Net forum: How does UpdatePanel work with ViewState? - Justin myJustin = new Justin( Expriences.Current );

Question from Tapuz .Net forum: How does UpdatePanel work with ViewState?

שאלה:

 משהו לא ברור לי איך UpdatePanel עובד עם ViewState.

אם ב-ViewState נשמר המצב של פקדי ה-Web שלנו, ואנחנו משנים את המצב הזה במהלך ריצת הדף, איך זה שה-ViewState חוזר לשרת אין חזרה למצב המקורי?

 

תשובה:

 בואו נבין את השאלה.

ניצור דף ASP.Net רגיל לכל דבר עם Label בעל הטקסט Hello World.

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!this.IsPostBack)

            Label1.Text = "hello world2";

    }

נביט על ה-Source של הדף.

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
   Untitled Page
</title></head>
<body>
    <form name="form1" method="post" action="Default11.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJODExMDE5NzY5D2QWAgIDD2QWAgIBDw8WA
h4EVGV4dAUMaGVsbG8gd29ybGQyZGRkgQasNLsHDgqB8VeiQz1R8R14xHE="
/>
</div> <div> <span id="Label1">hello world2</span> </div> </form> </body> </html>

 

 נשים לב שקיבלנו ערך נסתר בשם VIEWSTATE__ שמייצג את ה-ViewState של הדף.
ה-ViewState זאת אותה חיה מסתורית שחיה במעמקי ASP.Net ודואגת לטעון ערכים מחדש אחרי PostBack.

לאלה מאתנו שאינם קוראים קידוד 64 ביט לא מוצפן שוטף, ניקח את ה-ViewState הזה ונפרש אותו באמצעות תוכנה.
נשתמש ב-ViewState Decoder גירסה 2.1. נעתיק לתוכו את ה-ViewState שקיבלנו וזה מה שנראה:

 אפשר לראות ש-ViewState מורכב מ-Pair ו-ArrayList שמייצגים כנראה איזה היררכית פקדים. (בנוסף גם קיים Triplet שלא ראינו כאן).

נוסיף לדף שלנו כפתור שרק גורם ל-PostBack בלי שום דבר מיוחד. ונלחץ עליו.

הפלא ופלא, אחרי לחיצה על הכפתור, ריצה לשרת (שבא נזכר בזה שהשרת לא מחזיר את הערך לתוך Label באמצעות ה-Page_load) וחזרה ללקוח - יש עדיין את הטקסט hello world2.

איפה הערך הזה נשמר? בתוך ה-ViewState שראינו, והשרת בריצה בחזרה אליו יודע להחזיר את הערך לתוך Label1.Text.

עכשיו בואו נוסיף UpdatePanel לדף, נגרום לכפתור שלנו ליצור PostBack שקט שיעדכן את ערך ה-Label.

 

// in myPage.aspx.cs

public partial class Default11 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!this.IsPostBack)

            lblText.Text = "hello world2";

    }

    protected void btnSilentPostBack_Click(object sender, EventArgs e)

    {

        lblText.Text = "I was changed by UpdatePanel";

    }

}

 

// in myPage.aspx

 

    <form id="form1" runat="server">

        <div>

            <asp:ScriptManager ID="ScriptManager1" runat="server" />

 

            <asp:UpdatePanel ID="UpdatePanel1" runat="server">

 

                <ContentTemplate>

                    <asp:Label ID="lblText" runat="server" />

                </ContentTemplate>

 

                <Triggers>

                    <asp:AsyncPostBackTrigger ControlID="btnSilentPostBack" EventName="Click" />

                </Triggers>

 

            </asp:UpdatePanel>

 

            <asp:Button ID="btnSilentPostBack" runat="server" Text="Cause Silent PostBack" OnClick="btnSilentPostBack_Click" /><br/>

            <asp:Button ID="btnPostBack" runat="server" Text="Cause PostBack" OnClick="btnSilentPostBack_Click" />

        </div>

    </form>

אין פה שום דבר מיוחד מדי, יש לנו Label, שבלחיצה על הכפתור מתבצע PostBack שקט והטקסט של ה-Label בתוך ה-UpdatePanel מתעדכן.

בטעינת הדף נראה: (שלב א')

לאחר לחיצה על Silent PostBack נקבל (בלי רפרוש מלא של הדף) (שלב ב')

ועכשיו נלחץ על Cause PostBack שיגרום ריצה מלאה לשרת וחזרה ללקוח (שלב ג')

OK, ההתנהגות הגיונית. זה הרי מה שרצינו שיקרה.

אבל, בואו נביט על ה-ViewState לאחר שלב ב' (אחרי הלחיצה על ה-Silent PostBack)

 

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJODI0NTE
2NjUzD2QWAgIDD2QWAgIDD2QWAmYPZBYCAgEPDxYCHgRUZXh0BQxoZWxsbyB3b3JsZDJkZGTeg0TK+W
J21pvQbStDq55G3LB7CQ==/>

נפרש את זה:

בואו נבין מה אנחנו רואים כאן עכשיו - אחרי ה-Slient PostBack ה-ViewState הכתוב ב-Source של הדף הוא עדיין אותו ViewState בטעינת הדף. (הרי הדף לא מתפרשרש)

אז איך השרת יודע אחרי ה-PostBack האמיתי והמלא שהערך של ה-Text של ה-Label הוא "I was changed by postback"?

נתקין תוכנה קטנה בשם Fiddler מבית מיקרוסופט שמטרתה היא לעקוב אחרי ה-Request וה-Response מהדפדפן.

נבצע את שלב א' עוד פעם (נטען את הדף מחדש).

 

אנחנו רואים בפינה הימנית העליונה את הבקשה לשרת לדף נקי וחדש.
בפינה הימנית התחתונה נראה את התשובה של השרת.
בצד שמאל נראה אינדקס של כל הבקשות שבוצעו לשרת (אחת לדף ואחד לקובץ סקריפט חיצוני).

כעת, נלחץ על כפתור ה-Cause Silent PostBack שלנו ונראה את הבקשה והתשובה.

 

נקרא מה כתוב בפינה הימנית העליונה - לשרת נשלחת בקשה בצירוף ה-ViewState הנוכחי של הדף.
ה-ViewState שנשלח לשרת עבר UrlEncode (בדומה ל-QueryString) למעוניינים אפשר להעתיק את הערך לתוך המתודה Server.UrlDecode ולקבל את ה-ViewState. אם נביט על הערך של ה-ViewState שנשלח לשרת נראה:

נביט על הפינה הימנית התחתונה של Fiddler ונראה שקיבלנו בחזרה HTML שיוצג בתוך ה-UpdatePanel וגם ViewState כלשהו.
נפרש את ה-ViewState שהשרת מחזיר ונראה:

אז כנראה שהשרת מקבל את ה-ViewState המקורי ומחזיר את ה-ViewState של הדף אחרי השינוי שבוצע בשרת!

בואו גם נביט על ה-ViewState שבסופו של דבר נשלח לשרת אחרי PostBack מלא.

אם נפרש את ה-ViewState שנשלח לשרת ב-PostBack המלא נראה.

אז מה מסתבר? לשרת גם נשלח ה-ViewState המעודכן!

 

בואו נחזור על השלבים כפי שראינו אותם

  1. טעינת הדף - כל ה-ViewState כתוב כפי שהוא נשלח מהשרת.
  2. PostBack שקט - לשרת נשלח ה-ViewState המקורי והשרת מחזיר לנו את ערך ה-ViewState המעודכן.
  3. PostBack מלא - לשרת נשלח ה-ViewState המעודכן.

 

מה מסתבר? ש-Microsoft AJAX מקבל בחזרה תשובה מ-UpdatePanel הוא מעדכן את ה-ViewState של הדף.

כל ה-ViewState נשלח לשרת, וכל ה-ViewState נשלח בחזרה ללקוח, עם כל רפרוש של ה-UpdatePanel.

 

(חשוב להדגיש שהדוגמה כאן היא להמחשה בלבד על איך UpdatePanel מטפל ב-ViewState.
במצב הזה של עדכון Label יש פתרונות עדיפים מאשר לערב UpdatePanel שהוא פתרון מהיר אך בעל עלויות גבוהות כפי שראינו).

Published Thursday, May 31, 2007 6:23 PM by Justin-Josef Angel [MVP]

Comments

No Comments