FineUIMvc隨筆(5)UIHelper是個什么梗?


聲明:FineUIMvc(基礎版)是免費軟件,本系列文章適用於基礎版。

UIHelper.Result

在 FineUIMvc 的每一個 HttpPost 的控制器方法里面,你都會看到 UIHelper.Result():

 

這到底是個什么梗?在 ASP.NET MVC 中並沒有 UIHelper 這樣一個靜態類,為何它能頻頻出現於每個 HttpPost 的控制器方法中呢?

這一切的一切還要從 ActionResult 入手。

 

ActionResult

即使第一天接觸 ASP.NET MVC 開發人員也應該知道 ActionResult 的含義,作為控制器方法(Action)的返回值(Result),這是一個抽象類。

MVC 內置了很多 ActionResult 的實現類,最常用的可能是下面幾個:

1. ViewResult:返回視圖。

2. ContentResult:返回一個靜態字符串。

3. RedirectResult:重定向到另一個URL,類似於 WebForms 中的 Response.Redirect 函數,返回的HTTP狀態碼是 302 Redirect。

4. JsonResult:返回一個JSON字符串。

5. HttpNotFoundResult:未找到對象,一般用於URL參數錯誤,返回的HTTP狀態碼是 404 Not Found。

還有很多類似的實現,在學習過程中我們會逐步接觸。

 

但是這里面沒有 FineUIMvc 回發時能用的 ActionResult,如果你之前對 FineUI(開源版)有所了解的話,就知道 FineUI 回發時返回的是一串 JavaScript 代碼:

 

因此我們就需要自定義 ActionResult 的實現類,來在 FineUIMvc 回發時返回需要的 JavaScript 代碼,這個實現類就是 FineUIMvc.AjaxResult。

 

FineUIMvc.AjaxResult 會處理回發過程中每個控件的改變,並轉化為 JavaScript 代碼並返回。

比如這樣一段 C# 代碼:

Alert.Show("你好 FineUIMvc!", MessageBoxIcon.Warning);

 

在返回的 HTTP 響應中,對應於:

F.alert({message:'你好 FineUIMvc!',messageIcon:'warning'});

 

這個轉化過程就是有 FineUIMvc.AjaxResult 類負責的。

 

而 UIHelper.Result 就是返回的一個 AjaxResult 實例,內部實現如下:

public static class UIHelper
{
    
    /// <summary>
    /// 響應Ajax請求
    /// </summary>
    /// <returns></returns>
    public static AjaxResult Result()
    {
        return new AjaxResult();
    }
    
}

 

現在回過頭來,我們看下 ASP.NET MVC 中的 HttpPost 控制器方法中為啥不需要類似 AjaxResult 的實現:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name,Gender,Major,EntranceDate")] Student student)
{
       if (ModelState.IsValid)
       {
              db.Students.Add(student);
              db.SaveChanges();
              return RedirectToAction("Index");
       }
 
       return View(student);
}

可以看到,原生的 HttpPost 控制器方法直接返回的是視圖(ViewResult的實例),也就是整個頁面的更新,非AJAX過程。

 

UIHelper.Button,UIHelper.Grid,UIHelper.Tree... 

UIHelper 還有一個重要的用途,那就是根據控件的 ID 獲取控件對象,並對其進行更改,UIHelper.Result 會將所有的更改轉化為 JavaScript 並返回到客戶端。

 

下面通過一個例子來詳細說明這一過程:

在線示例地址:http://fineui.com/demo_mvc#/demo_mvc/Button/Button

 

在這個例子中,點擊第一個按鈕,會不斷切換第二個按鈕[按下的按鈕]的狀態,第一個按鈕的點擊事件處理函數:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult btnChangePressed_Click(bool pressed)
{
    UIHelper.Button("btnPressed").Pressed(!pressed);

    return UIHelper.Result();
}

 

這里面有幾個重要的概念:

1. 第二個按鈕的當前狀態需要通過客戶端傳入,服務器端對其一無所知(從 WebForms 轉入的開發人員常常會忽略這個重要概念)。

2. UIHelper.Button("btnPressed"),用來返回一個 ID 為 btnPressed 的按鈕示例。

3. Pressed 方法用來生成一段改變按下狀態的腳本。

 

一個常常令開發人員疑惑的事實是:UIHelper.Button("btnPressed") 返回的並不是你在 View 中定義的名為 btnPressed 的按鈕對象!

因為 HTTP 協議本身是無狀態,因此服務器端不可能知道客戶端的任何數據(除非你顯式傳入的數據),更無法得知你在 View 中定義的任何內容了。

是不是懷念 WebForms 了,因為在 WebForms 中 ViewState 幫你記下了所有的控件屬性,然而你不是很討厭 ViewState 的臃腫嗎?

 

讓我來做個簡單的說明,希望能解開你心中的疑惑,在 View 中,我們是這么定義按鈕的:

@(F.Button()
    .ID("btnPressed")
    .Text("按下的按鈕")
    .EnablePress(true)
    .Pressed(true)
)

在回發里面,如果你試圖獲取按鈕的 Text 屬性,你會發現這個是空字符串!

UIHelper.Button("btnPressed").Source.Text

因為在 FineUIMvc 內部,只是重新創建了一個 ID=btnPressed 的按鈕,默認按鈕的 Text 就是空字符串。

 

為了盡量避免開發人員犯這個錯誤,所有 UIHelper.Button, UIHelper.Grid... 返回實例中,只能通過方法來操作,比如更改按鈕的顯示文本:

UIHelper.Button("btnPressed").Text("修改成你想要的文本");

 

再次強調:UIHelper.Button 返回的是按鈕示例只是用來輔助生成前端 JavaScript 的更新腳本,不是 View 中定義的按鈕實例。

 

下面簡單看下,在前台如何傳入第二個按鈕的按下狀態:

@(F.Button()
    .ID("btnChangePressed")
    .Text("改變后面按鈕的按下狀態")
    .CssClass("marginr")
    .OnClick(Url.Action("btnChangePressed_Click"), new Parameter("pressed", "F.ui.btnPressed.isPressed()"))
)

通過上一篇文章講解的自定義參數,我們知道 Paramter 示例中的第二個參數是一段 JavaScript 代碼:

F.ui.btnPressed.isPressed()

 

小結

UIHelper 是一個非常重要的靜態類,它有兩個主要的用途。

UIHelper.Result 用來返回一個 FineUIMvc.AjaxResult 的實例,用來將回發時的更改轉化為 JavaScript 代碼返回。

另一個重要用途的返回控件實例(比如 UIHelper.Button,UIHelper.Grid,UIHelper.Tree...),並提供一系列的方法來更新控件,但是要注意這里的控件實例並不是你在 View 中定義的那個實例,只是一個新創建的同名實例而已,方便更新控件屬性。

 

《FineUIMvc隨筆》目錄:http://www.cnblogs.com/sanshi/p/6473592.html 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM