APS.NET MVC + EF (10)---使用AJAX
在Web系統中,Ajax技術已經成為提高用戶體驗的必備技術。開發Ajax程序,涉及兩方面的內容:一是客戶端技術,二是服務器端技術。
(1)客戶端技術
核心工作是通過JavaScript向服務器發送數據和接收數據。初次之外還涉及兩個工作,一是數據的展示,因此涉及Html DOM、CSS等相關技術;二是數據處理,因此涉及JSON、XML等數據格式處理技術。在實際開發過程中,可以借助一些客戶端框架,來提高工作效率。
(2)服務器端技術
核心工作是完成在服務器端接收和發送數據。
10.1 使用動作方法處理Ajax請求
在動作方法中處理Ajax請求,重點關註的是如何向客戶端返回數據。
對於接收數據,由於Ajax客戶端程序仍是通過Get或Post方式發送數據,因此處理方式和接收非Ajax請求一致。
向服務器端發送數據,一般有如下幾種形式。
10.1.1 返回純文本數據
對於向客戶端返回結構單一的數據,可以使用純文本格式,如刪除操作是否成功的提示,用法如示例1所示。
示例1
public ActionResult Delete(int? id) { //省略代碼 if(manager.Delete(id)) { return Content("1"); //操作成功 } return Content("0"); } |
對於示例1,客戶端接收的數據是"0"或"1",根據數據客戶端可做出刪除操作是否成功的提示。
10.1.2 返回分部視圖
對於局部刷新的效果,多數情況是向服務器端請求一個局部的頁面,示例2展示了針對Ajax請求返回一個分部視圖。
示例2
/// 獲取當前用戶的分組信息 public ActionResult ListGroups() { User user = Session["CurrentUser"] as User; if (user == null) { return this.Content("<script>window.location=‘" + Url.Action("Login", "Account") + "‘</script>"); } int userId = user.UserId; //分組列表數據 var groups = context.PrivateGroups.Where(a => a.OwnerId == userId).ToList(); //返回分部視圖 return PartialView("GroupList"); } |
註意使用PartialView()方法返回分部視圖。
10.1.3 返回結構化數據
如果向客戶端返回復雜結構的數據,一般需要由服務器端向客戶端返回客戶端支持的數據格式,如JSON格式和XML格式。在不同的服務器端平臺中,都有相應的API 支持將對象轉化成這些格式的數據。如示例3所示。
示例3
/// 獲取當前用戶分組信息 public ActionResult ListGroupsToJson() { User user = Session["CurrentUser"] as User; if (user == null) return Content(""); int userId = user.UserId; //分組列表數據 var groups = (from g in context.PrivateGroups where g.OwnerId == userId select g ).ToList(); return Json(groups,JsonRequestBehavior.AllowGet); } |
示例3中, Json()方法負責將對象序列化為JSON數據,其中第一個參數是要序列化的對象,第二個 JsonRequestBehavior 類型的參數,是一個枚舉類型,包含AllowGet 和 DenyGet 兩個值,分別代表允許Get 請求和不允許 Get 請求。
客戶端獲取JSON數據後,一般需要對JSON數據進行處理,以某種形式展示出來。多數情況會使用客戶端控件來處理,比如 BootStrapTables 。
? ?
在使用ASP.NET MVC 提供的 Json()方法返回JSON數據時,對待DateTime類型的數據處理往往不能滿足我們的要求。在實際開發中我們通常會使用 如下方法:
Newtonsoft.Json.JsonConvert.SerializeObject(object value)
示例3中的最後一行代碼可以換做如下:
return Content( JsonConvert.SerializeObject(groups) );
? ?
10.2 使用AjaxHelper
總的來說,在Ajax程序開發中,客戶端的編碼工作是必不可少的,但是如果使用ASP.NET MVC 框架,這些編碼工作就會大大減少,甚至在一些簡單的應用場景,不需要手工編寫JavaScript 代碼。
ASP.NET MVC 的這種功能是由 AjaxHelper 類型的對象提供的,此類和 HtmlHelper 是對應的,也是輔助視圖輸出的,特殊的是它用於生成具有Ajax功能的視圖。相應地,在視圖基類 WebViewPage 中包含名稱為 AjaxHelper 類型的對象 Ajax ,通過Ajax 對象調用相應的方法實現Ajax 功能視圖的輸出。
10.2.1 構造無刷新表單
最常見的一種場景是表單提交,在客戶端使用jQuery 時,一般會借助於 $.ajax() 和 $.post() 提交表單。其中,大部分的編碼工作是從表單中獲取提交的數據,工作量往往隨著表單的字段增加而增加。
在ASP.NET MVC 中,借助於 Ajax 對象提供的 BeginForm()方法,即可完成此功能。如下語法展示了BeginForm() 一個典型的重載版本定義。
? ?
public static MvcForm BeginForm(
this AjaxHelper ajaxHelper,
string actionName,
object routeValues,
AjaxOptions ajaxOptions
)
和 HtmlHelper 中的BeginForm() 不同的是,多了AjaxOption 類型的參數,通過該類對請求發送前後進行相關的設置,主要屬性如表10-1 所示。
表10-1 AjaxOptions 類的主要屬性
主要屬性 | 說 明 |
string UpdateTargetId | 服務器響應來更新的 DOM 元素的 ID |
string Confirm | 提交請求之前顯示在確認窗口中的消息 |
string HttpMethod | HTTP 請求方法("Get"或"Post") |
InsertionMode InsertionMode | 將響應插入目標 DOM 元素的模式,默認為Replace |
int LoadingElementDuration | 控制在顯示或隱藏加載元素時的動畫持續時間(毫秒) |
string OnBegin | 在更新頁面之前調用的 JavaScript 函數 |
string OnSuccess | 在成功更新頁面之後調用的 JavaScript 函數 |
string OnComplete | 在實例化相應數據後但在更新頁面前調用的JavaScript函數 |
string OnFailure | 在頁面更新失敗時調用的JavaScript 函數 |
string Url | 向服務器發送請求的 |
? ?
示例4展示了 Ajax.BeginForm()的使用方法。
示例4
@section scripts{ <script type="text/javascript" src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"> </script> } @using (Ajax.BeginForm("AddRecord", new AjaxOptions { UpdateTargetId = "AddRecordMessage" })) { <textarea name="Content" cols="" rows="" class="importArea"> 在想什麽呢?記下來吧</textarea> <p> <input type="submit" value="發 表 "/ class="button"> <a id="AddRecordMessage" class="message"></a></p> } //動作方法-添加記錄 [HttpPost] public ActionResult AddRecord(string Content) { if (ModelState.IsVaild) { Record record= new Record(); record.Content=Content; db.Records.Add(record); if (db.SaveChanges()>0) { return Content("記錄保存成功!"); } Else { return Content("記錄保存失敗!"); } } else { return Content("請按要求填寫信息!"); } } |
在示例4中,只用到 AjaxOption 類型的一個參數 UpdateTargetId ,其值為<a>標簽的Id屬性,<a>標簽用於顯示Ajax 方式提交後,從服務器端返回的消息提示。
需要註意使用ASP.NET MVC 提供的 Ajax 功能,需要引入 jquery.unobtrusive-ajax.min.js 腳本,該文件提供非侵入方式提供 Ajax 功能,而不生成Html 和 JavaScript 混合的代碼,這和驗證框架處理方式是一致的。示例4中 Ajax.BeginForm() 方法生成的Html 代碼如下。
? ?
<form action="/Home/AddRecord"
data-ajax="true" data-ajax-mode="replace"
data-ajax-update="#AddRecordMessage"
id="form0" method="post">
<!--省略代碼-->
</form>
對於一些簡單的應用場景,使用 Ajax.BeignForm()方法基本不需要手工編寫任何 JavaScript 腳本,但對一些特殊需求,還是需要編寫 JavaScripts 函數實現,這些函數可以通過 AjaxOptions 的屬性賦值進行調用。示例5 展示了 AjaxOptions 的 OnSucess 屬性和 Confirm 屬性的用法。
示例5
<script type="text/javascript"> function addRecordSuccess(data) { $("#AddRecordMessage").html(data).show().hide(5000); } </script> @using (Ajax.BeginForm("AddRecord", new AjaxOptions { OnSuccess = "addRecordSuccess", Confirm="確認要提交麽?" })) { <textarea name="Content" cols="" rows="" class="importArea"> 在想什麽呢?記下來吧 </textarea> <p> <input type="submit" value="發 表 "/ class="button"> <a id="AddRecordMessage" class="message"></a> </p> } |
在示例5代碼中,OnSucess 屬性設置為 JavaScript 函數 addRecordsSuccess(), 使用函數實現消息顯示後在5秒內自動隱藏。另外,使用 Confirm 彈出提交前的確認提示框。
10.2.2 生成無刷新鏈接
除了表單提交外,還有一個典型的應用場景,當點擊一個鏈接時,在同一個頁面局部加載頁面內容。對於這種場景,Ajax對象提供了兩種生成Ajax鏈接的方法,即 Ajax.ActionLink() 和 Ajax.RouteLink() ,和Html對象的兩個對應的方法相比,多了一個AjaxOption參數。如示例6所示。
示例6
<ul class="friendCatalog" id="groupItems"> @foreach (Friends.Models.PrivateGroup m in ViewBag.Groups) { <li> @Ajax.ActionLink(m.GroupName,"ListFriends","Friend", new{groupId=m.GroupId}, new AjaxOptions(){OnSuccess="loadFriendsByGroup"}) <img src="@Url.Content("~/images/edit.gif")" /> <img src="@Url.Content("~/images/delete.gif")" /><span> @m.FriendRelations.Count()</span> </li> } <!--省略部分代碼--> </ul> |
示例6運行後,Ajax.ActionLink()對應生成的Html代碼如下所示。
<a data-ajax="true" data-ajax-success="loadFriendsByGroup"
href="/Friend/ListFriends?groupId=4">鏈接內容</a>
? ?
? ?
? ?
? ?
? ?
? ?
? ?
? ?
APS.NET MVC + EF (10)---使用AJAX