1. 程式人生 > >FineUIMvc隨筆(3)不能忘卻的回發(__doPostBack)

FineUIMvc隨筆(3)不能忘卻的回發(__doPostBack)

 宣告:FineUIMvc(基礎版)是免費軟體,本系列文章適用於基礎版。

使用者反饋

有網友在官方論壇丟擲了這麼一個問題,似乎對 FineUIMvc 中的瀏覽器端與伺服器端的互動方式很有異議。

這裡面的關鍵詞就是:回發!

似乎一提到回發(__doPostBack),就讓人聯想到 WebForms 中的 ViewState 和單表單提交,因為回發時會把頁面上所有控制元件的 ViewState 一股腦的提交到後臺,無疑加重了網路的上行資料量。從此 回發 這一名詞給人的印象就很晦澀了。

真的是這樣嗎?我們分別來比較 WebForms、ASP.NET MVC、以及FineUIMvc中的回發,來探索其中的聯絡和差異。

WebForms中的回發(__doPostBack)

每位經歷過 ASP.NET WebForms 的開發人員都不會忘記這個字串:__doPostBack,因為它出現在你寫的每一個 .aspx 頁面的瀏覽器原始碼中:

<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    
if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } //]]> </script>

在 WebForms 中,整個頁面就是一個表單,所以早期的微軟工程師大搖大擺的定義了一個全域性變數:

var theForm = document.forms['form1'];

__doPostBack 函式則是對頁面上這個唯一的表單提交( theForm.submit),傳入的 eventTarget 和 eventArgument 分別用來標識本次回發的觸發控制元件以及回發引數。

這些都沒啥,關鍵是頁面上永遠都有一個 ViewState 隱藏欄位:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTQyNjcyNDU5MWRkpK.....aycxe0NfpWe+PGI0=" />

這裡面存放了頁面上所有控制元件的狀態資訊,比如下拉列表的資料,表格的資料,輸入框的資料等等,所有這個欄位一般會比較大,導致上傳的資料量動輒就有20K~1000K。在網路有限的情況下會非常影響效能,從而給人了臃腫的印象。

比如在 FineUI(開源版)中一個包含表格的頁面:

http://fineui.com/demo/iframe/grid_iframe.aspx

頁面回發時,請求的資料量就達到 19802 bytes = 19K

ASP.NET MVC中的回發(BegionForm)

在 ASP.NET MVC 中,我們可以定義多個表單,從而自行控制需要提交的表單,以及表單中欄位。也就是隻提交我們需要的資料,這樣不僅靈活而且上傳資料量不會很大。

在 MVC 的其他文件中,你可能很少會看到 回發 這個字眼,很多是這樣描述的:提交某個表單到控制器的某個操作方法,或者說發起一個 HTTP POST 請求。其實這些都對應於 WebForms 中的回發字眼,只不過操作的表單和表單欄位不同而已。本質上還是一樣的。

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <p>
        所學專業: @Html.DropDownList("Major", ViewBag.MajorList as IEnumerable<SelectListItem>, "全部")
        姓名: @Html.TextBox("Name")
        <input type="submit" value="檢索" />
    </p>
}

通過 Html.BeginForm 輔助方法來生成一個表單,這個表單會提交到當前頁面對應的控制器方法,預設使用 POST 請求,生成到頁面的HTML結構類似:

<form action="/Students/Create" method="post">
    
</form>

表格裡面,明確定義了兩個表單欄位,分別是 Major 和 Name,以及一個提交按鈕(type=submit)。

對應的後臺控制器方法類似:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string Major, string Name)
{
    // ...
    return View(students.ToList());
}

在這個過程中,雖然我們可以控制要提交的表單,以及提交哪些引數,但這個過程還是整個頁面提交。

而 FineUIMvc 中,我們不僅不需要定義表單(只需要告訴FineUIMvc需要提交哪些引數即可),而且所有的提交都是AJAX過程。

FineUIMvc中的回發(OnClick、OnPageIndexChanged)

FineUIMvc中將對控制器方法的呼叫放到每個具體的控制元件中, 對應於 FineUI(開源版)中控制元件的事件。

無引數回發

按鈕的點選事件:

@(F.Button()
    .OnClick(Url.Action("btnHello_Click"))
    .ID("btnHello")
    .Text("點選彈出對話方塊")
)

這樣就將按鈕的客戶端點選事件(click)和伺服器端控制器的方法(btnHello_Click)關聯起來,而且命名也和WebForms中的一模一樣,是不是倍感親切。

仔細觀察下這個 HTTP 請求,我們就能知道這個客戶端點選事件將去向何方:

從這張圖上,我們有如下收穫:

  1. Basic是區域名稱(Area),Hello是當前控制器名稱
  2. btnHello_Click是點選按鈕時對應的控制器方法
  3. 請求方法是 POST
  4. X-Requested-Width: XMLHttpRequest,表明當前請求是AJAX

再來看下HTTP請求正文資料:

只要一個防止跨站請求偽造(CSRF)的引數_RequestVerificationToken,再無其他引數。

對應的控制器方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult btnHello_Click()
{
    Alert.Show("你好 FineUIMvc!", MessageBoxIcon.Warning);

    return UIHelper.Result();
}

因為在這個過程中,後臺無需引數,所以前臺也沒必要傳入任何資料。這樣一個AJAX回發過程就非常乾淨,不像之前的WebForms一樣,需要傳遞一堆引數了。

帶引數回發

來看下錶格的資料庫分頁事件,在資料庫分頁時後臺C#程式碼需要知道兩個引數:

1. 當前的頁碼

2. 表格中用到了哪些資料庫欄位,即使熟練的WebForms開發人員可能也不會意識到這一點,因為在WebForms中後臺能夠知道控制元件的所有引數,而MVC中回發時,你對錶格的任何引數一無所知,所有你需要的引數都需要通過前臺傳入

FineUIMvc對於帶引數的回發回發進行了深度優化,你根本無需自己通過JavaScript來獲取這些引數(當然你也可以這麼做,只要你願意),而是指定表格的ID即可:

@(F.Grid()
    .EnableCheckBoxSelect(true)
    .Width(850)
    .ShowHeader(true)
    .ShowBorder(true)
    .EnableCollapse(true)
    .Title("表格")
    .ID("Grid1")
    .DataIDField("Id")
    .DataTextField("Name")
    .AllowPaging(true)
    .PageSize(5)
    .IsDatabasePaging(true)
    .OnPageIndexChanged(Url.Action("Grid1_PageIndexChanged"), "Grid1")
    .Columns(
        F.RowNumberField(),
        F.RenderField()
            .HeaderText("姓名")
            .DataField("Name")
            .Width(80),
        ....
    )
    .RecordCount(ViewBag.Grid1RecordCount)
    .DataSource(ViewBag.Grid1DataSource)
)

注意 OnPageIndexChanged 的第二個引數,這樣在發起對控制器方法(Grid1_PageIndexChanged)的POST請求時,會自動附加所需的引數:

對應的控制器方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Grid1_PageIndexChanged(JArray Grid1_fields, int Grid1_pageIndex)
{
    var grid1 = UIHelper.Grid("Grid1");

    var recordCount = DataSourceUtil.GetTotalCount();

    // 1.設定總項數(資料庫分頁回發時,如果總記錄數不變,可以不設定RecordCount)
    grid1.RecordCount(recordCount);

    // 2.獲取當前分頁資料
    var dataSource = DataSourceUtil.GetPagedDataTable(pageIndex: Grid1_pageIndex, pageSize: 5, recordCount: recordCount);
    grid1.DataSource(dataSource, Grid1_fields);

    return UIHelper.Result();
}

小結

WebForms中的回發由於需要附加上ViewState而略顯臃腫;

ASP.NET MVC原生的回發需要藉助Html.BeginForm輔助方法來生成單獨的表單,並把需要提交的引數放置到表單中,回發過程是整個頁面提交;

FineUIMvc對回發過程進行深度優化,無需建立表單,只需要提供需要回發的引數,而且回發過程是AJAX的。對於部分控制元件比如表單和表格,甚至不需要指定回發引數,只需要設定控制元件ID即可,非常方便。

如果你還對WebForms中的回發念念不忘,那就無需忘卻。 

相關推薦

FineUIMvc隨筆3不能忘卻__doPostBack

 宣告:FineUIMvc(基礎版)是免費軟體,本系列文章適用於基礎版。 使用者反饋 有網友在官方論壇丟擲了這麼一個問題,似乎對 FineUIMvc 中的瀏覽器端與伺服器端的互動方式很有異議。 這裡面的關鍵詞就是:回發! 似乎一提到回發(__doPostBack),就讓人聯想到 Web

MySQL表類型MyISAM/InnoDB的區別解決事務不滾的問題

span into article one 工具 tab select var pan MyISAM:這個是默認類型,它是基於傳統的ISAM類型,ISAM是Indexed Sequential Access Method (有索引的順序訪問方法) 的縮寫,它是存儲記錄和文件

Android2017最新面試題3-5年經驗個人面試經歷

asynctask 今天 nds tom 隨著 進程 處理 ror ron 2017最新Android面試題 大家好,在跟大家講述自己的面試經歷,以及遇到的面試題前,先說說幾句題外話。 接觸Android已經3年,在工作中遇到疑難問題總是在網上(csdn大牛博客,stack

Java發展的時間表。 版本號 名稱 中文名 布日期

時間日期 jtable beta 編譯 5.0 企業版 evel 簡化 正版 JDK 1.1.4 Sparkler 寶石 1997-09-12  JDK 1.1.5 Pumpkin 南瓜 1997-12-13  JDK 1.1.6 Abigail 阿比蓋爾--女子名 199

Java學習不走彎路教程3.從文件內容查詢開始

輔助 pass 多說 font sys sta case index exe 一. 前言在前兩章教程中,分別介紹了DOS環境搭建和Eclipse環境搭建。本章將帶大家實現用簡單SQL語句查詢文件。註:1.本文針對初學Java的同學訓練學習思路,請不要太糾結於細節問題。2.本

Ardupilot飛控log程式碼學習3.6版本飛控韌體

目錄 文章目錄 目錄 摘要 1.官網資料學習 新增一個新的日誌訊息(Adding a new Log Message) 簡單的方法(The Easy Way) 複雜的方法(The Harder Way)

阿里App支付服務端介面開發含後臺非同步撥,退款

1.引入相關包檔案 maven匯入方式: <dependency> <groupId>com.alipay</groupId> <artifactId>sdk-java</artifactId> <version>

jzoj5895 【NOIP2018模擬10.5】旅遊 求歐拉路,性質

題目描述 分析 一個無向圖存在歐拉回路當且僅當所有的點的度數為偶數,所以需要在每一對奇點之間連一條邊然而觀察這題這題的邊權,發現所有比某條邊小的邊之和比這條邊小。那也就是說最短路必定在最小生成樹上。這就變成了最小生成樹上的配對問題。只要保證不走重邊,結果一定是一樣的。一棵子

Android2017-2018最新面試題3-5年經驗個人面試經歷

2017-2018最新Android面試題 大家好,在跟大家講述自己的面試經歷,以及遇到的面試題前,先說說幾句題外話。 接觸Android已經3年,在工

redis 叢集3.0版本開始支援叢集功能

叢集簡介 Redis 叢集是一個可以在多個 Redis 節點之間進行資料共享的設施(installation)。 Redis 叢集不支援那些需要同時處理多個鍵的 Redis 命令, 因為執行這些命令需要在多個 Redis 節點之間移動資料, 並且在高負載的情況下, 這

Java 9 揭祕3. 建立你的第一個模組

文 by / 林本託 Tips 做一個終身學習的人。 在這個章節中,主要介紹以下內容: 如何編寫模組化的Java程式 如何編譯模組化程式 如何將模組的專案打包成模組化的JAR檔案 如何執行模組化程式 在本章中,將介紹如何使用模組 —— 從編寫原始碼到編譯,打包和執行程式。 本章分為兩部分。 第一部分

快排的優化策略3種快排4種優化

1、快速排序的基本思想: 快速排序使用分治的思想,通過一趟排序將待排序列分割成兩部分,其中一部分記錄的關鍵字均比另一部分記錄的關鍵字小。之後分別對這兩部分記錄繼續進行排序,以達到整個序列有序的目的。 2、快速排序的三個步驟: (1)選擇基準:在待排序列中,按照某種方式挑出一個元素,作為 “基準”(piv

第五週 課後實踐--閱讀程式3,4,5,6

問題及程式碼: /* *Copyright (c) 2015,煙臺大學計算機學院 *All rights reserved. *檔名稱:test.cpp *作者:吳勝男 *完成日期:2015年04月08日 *版本號:v1.0 * *問題描述:本週再補充三個和指標有關的閱讀

js中簡易選項卡的實現3種方法實現樣式的封裝

清除浮動的三種方式 1.overflow: hidden; 清除子元素的浮動對父元素的影響 2.clear: both; 清除哥哥元素的浮動對弟弟元素的影響 3.:after{ display: block; content: “”; clear: bo

FineUIMvc隨筆4自定義引數與自定義

宣告:FineUIMvc(基礎版)是免費軟體,本系列文章適用於基礎版。 不能忘卻的回發 在上一篇文章中,我們對FineUIMvc中的回發進行了詳細描述,目的是為了告訴大家: 1. FineUIMvc中的回發其實是請求控制器方法的另一種表述而已 2. 回發是輕量級,只會傳入你允許傳入的引數 3. 回發

FineUIPro v3.6.0 布了3 年助力 200 家企業的信息化建設

自定義消息 比較 自定義 信任 logs idt 滾動條 資料 建設 FineUI(專業版)自從 2014-07-30 發布第一個版本以來,3 年來已經持續更新了 25 個版本,我們的堅持有目共睹,同時也受到了 200 家企業的青睞和信任,感謝一路有你。 FineU

JS知識整理隨筆3數組

.... nat 一個 .so 項目 stat 分享 它的 處的 創建數組 使用Array構造函數 語法:new Array() 小括號說明 預先知道數組要保存的項目數量 向Array構造函數中傳遞數組應包含的項 使用數組字面量表示法 由一對包含數組項的方括號[]表示,

node.js初步了解3——慕課網調,作用域,上下文

span clas global ava 運行 time log timeout color 1. 1 //回調:回調是異步編程最基本的方法,node.js需要按順序執行異步邏輯的時候,一般采用後續傳遞的方式,將後續邏輯封裝在回調函數中,作為起始函數的參數。 2 //

微信開發3 -- 支付後接收調信息測試

哪裏 是我 測試 們的 支付 ack 神馬 img 二維碼 場景:例如購買商品彈出支付二維碼,用戶掃碼支付後,微信服務器會回調本次支付的結果到你的服務器。 我們需要知道這次支付的結果,但是我們該怎麽測試呢?請往下看 1.設置回調地址 微信服務器會發信息到我們的系統,但是

Python之 並編程3-19

tool 工業 主存 軟件 個人計算機 應用程序 調用接口 隔離 總結 1946年第一臺計算機誕生--20世紀50年代中期,計算機工作還在采用手工操作方式。此時還沒有操作系統的概念。   程序員將對應於程序和數據的已穿孔的紙帶(或卡片)裝入輸入機,然