日期: 2023.10.17 星期四

狀態管理式網頁好重要的環節,Client 端發出請求給伺服器後就會斷線,執行過程中所有生成的資料都不會保存。

問題: 若有些資料需儲存起來怎麼辦

ViewStatge 技術乃指 Client 發出請求給伺服器端時,伺服器端會利用 ViewState 技術先儲存特定資料在 postback 後的 html 頁面上,等下一次做 PostBack 時(即回傳結果於 Client 時),再取出該資料作應用。

  1. 產生一 Web 表單,名稱 WebForm1
  2. UI 介面:

    • Label1
    • Button (按下顯示 PostBack 幾次於 Label1.Text 上) 只有按下第一次不是 PostBack, 其他次都是 PostBack
  3. Button1 事件

    Button1_Click(){
      int counter;
      //不存在該物件 ViewState["counter"] 時
      if(ViewState["counter"] == null){
        counter = 1;
      }else{
        counter = (int) ViewState["counter"] + 1;
      }
      //做完之後重新設定(刷新) ViewStage 的值
      ViewState["counter"] = counter;
      Label1.Text = counter.ToString();
    }

    ViewState 執行表單 WebForm1.aspx 將值提交給伺服器端後就會消失,但是它在提交時,表單內有一隱藏欄位會記錄該值,檢視原始碼,顯示的該內容是上一次執行完 WebForm1.aspx 回傳的 html 結果畫面: server 回傳結果時會自動加一個隱藏欄位填加該加一後的 count 值放在屬性 value="xxx" 裡面其中

    <form>
      :
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="64bit 的編碼,乃為 viewstate 的資料"
      :
    <input type=submit>
    </form>

    value 值紀錄 label1 屬性與 Button1 屬性 與 coumter 的值,當按下 Button1 就會提交(submit)該 value,提交到伺服器端,伺服器會將該 __VIEWSTATE 的值解碼得到該相對值。

練習

寫一 web form,上面有一 TextBoxTextBox 上可以輸入任何文字,有 3 個按鈕,第一個按鈕是 submit,按下去會把 TextBox 輸入的內容顯示在 Label1 上,另一個按鈕 "儲存" 當按下該按鈕會儲存該 TextBox1 輸入的值,
另一個按鈕 "還原",當按下時會把之前儲存起來的值顯示在 TextBox 上。 (不管你按了多少次 Submit, 當按下 "還原" 按鈕就會還原該儲存過後的值於 TextBox1 上)

解答

給一 WebForm2.aspx 表單後, 新增 TextBox1Button *3 ("Submit"、"Save"、"Resume"),Label1 (顯示 Submit 後的結果)

  1. 雙擊 Submit 按鈕,產生

    Button1_Click(){
      Label1.Text = TextBox1.Text;
    }
  2. 雙擊 Save 按鈕,產生

    Button2_Click(){
      ViewState["content"] = TextBox1.Text;
    }
  3. 雙擊 Resume 按鈕,產生

    Button3_Click(){
      //是否無值,即未曾按下 "Save" 按鈕
      if(ViewState["content"] == null){
        Label1.Text = "No saved data";
      }else{
    
         TextBox1.Text = ViewState["content"].ToString();
      }
    }
  4. 測試執行 WebForm2.aspx
  5. 到目前都是單一網頁執行,接下來是跨網頁(網頁間溝通與傳遞資料):

網頁間如何做到跳轉

http 協定來說,client 端會送一 Request 物件給 Server, 要求 Server 作一些事情, Server 端處理完事件後會下載一 Response 物件給 Client
你的瀏覽器根據收到的 Response 物件,解析後刷新頁面

  1. UI: 如下,按下 WebFomr1 上的 WebForm2 按鈕會執行表單 WebForm2.aspx

    WebForm1
    WebForm2
    Label1

    Button1(名稱: Button): 按一次 Label1+1, Button2(名稱: WebForm2): 按一下跳轉 WebForm2

  2. 方法 1: Response.Redirect(url), 雙擊 WebForm1.aspx 表單上的 Button2 按鈕

    Button2_Click(){
      //Client 端要要求 Server 端去執行 WebForm2
      //Response 物件要求 Browser 收到該 Response 物件時,馬上在下一個 URL 指令給伺服器
      Response.Redirect("WebForm2.aspx");
    }
  3. 方法 2: Server.Transfer()
    WebForm1 上多加一個按鈕 WebForm2+
    雙擊 WebForm1.aspx 表單上的 WebForm2+ 按鈕

    Button3_Click(){
      //Server 物件的 `Transfer()` 方法,告訴 Server 要轉移到哪一個地方
      Server.Transfer("WebForm2.aspx");
    }

    方法 1 與方法 2 都是跳轉頁面的功能,但是調用 Server.Transfer() 這方法執行後,其網址仍停留於原位置。 http://localhost:55212/WebForm1.aspx , 而不是 http://localhost:55212/WebForm2.aspx
    原因:
    執行 Response.Redirect(url) 時,即執行 WebForm2 按鈕時,你的瀏覽器會至少送出兩次 Request 物件。
    WebForm1 頁面上,第一次 Request 時機是當按下按鈕 WebForm2 要跳轉頁面的需求,執行完畢後產生 Response 物件,Server 端會下載 Response 物件給使用者端後,當 Client 端收到 Response 物件
    看到 Response 物件有一 Redirect() 方法,即是要求告訴瀏覽器馬上在連接到 Server 端去執行 WebForm2.aspx 頁面(第二次 Request),所以網址會變成 http://localhost:55212/WebForm2.aspx

    若 Server 的 Transfer() 方法,當執行 WebForm1,按下是按鈕 Button3_Click() 做了 Server 的 Transfer() 方法後,會結束 WebForm1 後面的所有程序 ,不在往後執行,直接告訴 Server 去執行 WebFomr2,執行後得到結果下載下來給使用者看,所以看到的是 WebForm2 執行的內容結果,但這時網址不會有任何變化,仍維持在 http://localhost:55212/WebForm1.aspx , 所以只有一次的 Request

頁面資料做轉移

方法 1. Cookie: Client 端上小檔案

  1. UI

    表單

    WebForm1
    WebForm2
    WebForm3
    WebForm4

  2. WebForm3 表單上

    TextBox1 輸入資料
    Button11 將資料傳到 WebForm4

  3. WebForm4 表單上
    Label1 顯示接收來至 WebForm3textBox1 的資料

  4. 雙擊 WebForm3.Button1_Click

    Button1_Click(){
      //資料存在 Client 端,不能用 ViewState 因是使用於不同頁面
      HttpCookie cc = new HttpCookie("hello"); //建構式參數需指定 Cookie 名稱
      //單一值時
      cc.Value = TextBox1.Text;
      //多值時用 Collection 物件。 Values
      //cc.Values.Add("name", TextBox1.Text);
      //cc["name"] = TextBox1.Text;
      //有效期間, 1 年後失效
      cc.Expires=DateTime.Now.addYears(1);
      //如何下載給使用者,透過 Response 物件的屬性 Cookies 將多個 Cookie 資料封裝起來
      Response.Cookies.Add(cc)
      //下載 Response 物件後執行 WebForm4.aspx
      Response.Redirect("WebForm4.aspx");
    }
  5. WebForm4.aspx

    Page_Load(){
      //透過 Request 取的上傳的 Cookie
      HttpCookie cc = Request.Cookies["name"];
      if (cc != null)
        Label1.Text = cc["name"];
      else
        Label1.Text = "No cookies";
      }
    }

方法 2. QueryString() 方法,即 http 的 GET

  1. WebForm3.aspx.cs

    “`C#
    protected void Button1_Click(object sender, EventArgs e){
    string r = TextBox1.Text;
    // 代表 QueryString 有有變數 name 與 age
    // 其中 & 是 url 中特殊符號
    // 使用此方法會將資料顯示網址上,不安全
    Response.Redirect("WebForm4.aspx?name=" + r + "&age=13");
    //所以改用 Server.Transfer() 就不會將資料顯示在網址上
    //Serve.Transfer("WebForm4.aspx?name=" + r);
    }

  2. WebForm4.aspx.cs

    “`C#
    protected void Page_Load(object sender, EventArgs e){
    //接收 URL 上傳遞過來的值
    Label1.Text = Request.QueryString["name"];
    }

  3. 測試:

    • 執行 WebForm3.aspx.c,輸入框輸入 abc,按下 按鈕,會轉向 WebForm4.aspx.cs 的網頁,網址: localhost:55212/WebFrom4.aspx?name=abc。 畫面結果輸出正常

    問題::

    因需要看網址的變化內容,WebForm3.aspx.csButton1_Click 上使用 Response.Redirect("WebForm4.aspx?name=" + r + "&age=13"); 方法

    執行 WebForm3.aspx.c,輸入框輸入 abc&123,按下 按鈕,會轉向 WebForm4.aspx.cs 的網頁,畫面結果輸出只有字串 abc,不正常,但網址顯示的是正確的訊息 localhost:55212/WebFrom4.aspx?name=123

    原因:
    HTTP 協定中,很多符號有特殊意義,例如: & 符號在 url 代表是參數跟參數的分隔。例如: 在
    WebForm3.aspx.cButton1_Click 上寫 Response.Redirect("WebForm4.aspx?name=" + r + "&age=13"); 代表在 Query String 內有兩變數(nameage),其中 & 符號是 url 的特殊符號,1 表示空白,所以後面的資料 age=13 會被切掉,但網路上有需要傳遞這些特殊符號資料,解決辦法針對使用者輸入資料做編碼(會將特殊符號轉成一個百分比符號加上二位數字),所以改寫如下:

    解決:
    WebForm3.aspx.cs

    protected void Button1_Click(object sender, EventArgs e){
      string r = TextBox1.Text;
      Response.Redirect("WebForm4.aspx?name=" + Server.UrlEncoder(r) );

    WebForm4.aspx.cs

    “`C#
    protected void Page_Load(object sender, EventArgs e){
    //接收 URL 上傳遞過來的值
    //Label1.Text = Server.UrlDecorder(Request.QueryString["name"]);
    //但不寫也可以自動做解碼
    Label1.Text = Request.QueryString["name"];
    }

    
    
    **測試**:
    修改後執行 `WebForm3.aspx.c`,輸入框輸入 `abc&123`,按下 `按鈕`,會轉向 `WebForm4.aspx.cs` 的網頁,畫面結果輸出正常而且 `URL` 也顯示的是正確的訊息 `localhost:55212/WebFrom4.aspx?name=123`。
  4. 練習
    在網頁中輸入兩數字,這兩數字相乘後結果傳送到另一網頁做顯示。

    1. 作法 1: 在第一網頁做出相乘結果在送至第二頁面。
    2. 作法 2: 在第一網頁先送出兩數資料後,在到第二網頁相乘,然後結果秀在第二頁面。

    解答:

    1. 產生兩 WebForm 表單(WebForm5.aspx.csWebForm6.spx.cs)
      • WebForm5.aspx.csUI1 標籤
      • WebForm6.aspx.csUI2 輸入文字框1 按鈕
    2. 雙擊 WebForm6.aspx.cs按鈕

      protected void Button1_Click(object sender, EventArgs e){
        string n1 = TextBox1.Text;
        string n2 = TextBox2.Text;
        Response.Redirect("WebForm5.aspx?n1=" + n1 + "&n2=" + n2 );

      網際網路上所傳遞的資料都是字串

    3. 回到 WebForm5.aspx.cs

      “`C#
      protected void Page_Load(object sender, EventArgs e){
      int n1 = Int32.Parse(Request.QueryString["n1"]);
      int n2 = Int32.Parse(Request.QueryString["n2"]);
      Label1.Tet = (n1*n2).ToString();
      }

最後修改日期: 2023 年 11 月 22 日

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。