聲明:FineUIMvc(基礎版)是免費軟件,本系列文章適用於基礎版。javascript
有網友在官方論壇拋出了這麼一個問題,彷佛對 FineUIMvc 中的瀏覽器端與服務器端的交互方式頗有異議。html
這裏面的關鍵詞就是:回發!java
彷佛一提到回發(__doPostBack),就讓人聯想到 WebForms 中的 ViewState 和單表單提交,由於回發時會把頁面上全部控件的 ViewState 一股腦的提交到後臺,無疑加劇了網絡的上行數據量。今後 回發 這一名詞給人的印象就很晦澀了。數據庫
真的是這樣嗎?咱們分別來比較 WebForms、ASP.NET MVC、以及FineUIMvc中的回發,來探索其中的聯繫和差別。瀏覽器
每位經歷過 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 隱藏字段:post
<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 中,咱們能夠定義多個表單,從而自行控制須要提交的表單,以及表單中字段。也就是隻提交咱們須要的數據,這樣不只靈活並且上傳數據量不會很大。
在 MVC 的其餘文檔中,你可能不多會看到 回發 這個字眼,不少是這樣描述的:提交某個表單到控制器的某個操做方法,或者說發起一個 HTTP POST 請求。其實這些都對應於 WebForms 中的回發字眼,只不過操做的表單和表單字段不一樣而已。本質上仍是同樣的。
在我以前寫MVC系列教程中有一個典型的回發過程:【第四篇】ASP.NET MVC快速入門之完整示例(MVC5+EF6)
@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中將對控制器方法的調用放到每一個具體的控件中, 對應於 FineUI(開源版)中控件的事件。
按鈕的點擊事件:
@(F.Button() .OnClick(Url.Action("btnHello_Click")) .ID("btnHello") .Text("點擊彈出對話框") )
這樣就將按鈕的客戶端點擊事件(click)和服務器端控制器的方法(btnHello_Click)關聯起來,並且命名也和WebForms中的如出一轍,是否是倍感親切。
仔細觀察下這個 HTTP 請求,咱們就能知道這個客戶端點擊事件將去向何方:
從這張圖上,咱們有以下收穫:
再來看下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中的回發念念不忘,那就無需忘卻。