Asp.Net MVC4系列--進階篇之AJAX
本章將開始介紹MVC中Ajax的使用
以一個非Ajax版本開始
Controller
public class PeopleController : Controller
{
private readonly Person[] _personData = {
new Person {FirstName = "Iori",LastName = "Lan", Role = Role.Admin},
new Person {FirstName = "Edwin", LastName= "Sanderson", Role = Role.Admin},
new Person {FirstName = "John",LastName = "Griffyth", Role = Role.User},
new Person {FirstName = "Tik",LastName = "Smith", Role = Role.User},
new Person {FirstName = "Anne",LastName = "Jones", Role = Role.Guest}
};
public ActionResult Index()
{
return View("List");
}
public ActionResult GetPeople()
{
return View("List",_personData);
}
[HttpPost]
public ActionResult GetPeople(string selectedRole)
{
if (selectedRole == null || selectedRole == "All")
{
returnView("List",_personData);
}
var selected = (Role)Enum.Parse(typeof(Role), selectedRole);
return View("List",_personData.Where(p => p.Role ==selected));
}
}
Model
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Role Role { get; set; }
}
public enum Role
{
Admin,
User,
Guest
}
View
@{
Layout = null;
}
@using MVCAjax.Models
@model IEnumerable<Person>
@{
ViewBag.Title = "GetPeople";
}
<h2>Get People</h2>
<table>
<thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
<tbody>
@foreach (var p in Model) {
<tr>
<td>@p.FirstName</td>
<td>@p.LastName</td>
<td>@p.Role</td>
</tr>
}
</tbody>
</table>
@using (Html.BeginForm()) {
<div>
@Html.DropDownList("selectedRole",new SelectList(
new []{"All"}.Concat(Enum.GetNames(typeof(Role)))))
<button type="submit">Submit</button>
</div>
}
測試:
驗證請求型別
在IE中開啟F12->Network ,我們可以看到請求的發起者是click操作,因為不是xmlHttpRequest,因而不是ajax請求
使用Ajax重構程式碼
配置Unobstrusiveajax
開啟web.config
確保這一行在appconfig節點中:
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
開啟App_Start/BundleConfig.cs,確保已新增(預設已新增):
bundles.Add(newScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
原因:我們需要的是jquery.1.7.1.js 和jquery.unobstrucsive-ajax.min.js,這兩個包已經包含了,在layout中render就可以了。
開啟_layout.cshtml
在<head>中render 這兩個包:
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
注意:在View確保沒有把@{layout=null},否則layout沒有應用導致沒有renderbundle,以致於無法render需要的script。
Controller 新增Action:
public ActionResult AjaxGetPeople()
{
return View("AjaxList");
}
public PartialViewResult GetPeoplePartial(string selectedRole = "All")
{
IEnumerable<Person> data = _personData;
if(selectedRole != "All")
{
var selected = (Role)Enum.Parse(typeof(Role), selectedRole);
data =_personData.Where(p => p.Role == selected);
}
return PartialView("PeoplePartialList",data);
}
新增PartialViewPeoplePartialList.cshtml :
@using MVCAjax.Models
@model IEnumerable<Person>
@foreach (Person p in Model) {
<tr>
<td>@p.FirstName</td>
<td>@p.LastName</td>
<td>@p.Role</td>
</tr>
}
新增View: AjaxList.cshtml :
@using MVCAjax.Models
@model string
@{
ViewBag.Title = "GetPeople";
var ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody"
};
}
<h2>Get People</h2>
<table>
<thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
<tbody id="tableBody">
@Html.Action("GetPeoplePartial", new {selectedRole= Model })
</tbody>
</table>
@using(Ajax.BeginForm("GetPeoplePartial",ajaxOpts)) {
<div>
@Html.DropDownList("selectedRole", new SelectList(
new []{"All"}.Concat(Enum.GetNames(typeof(Role)))))
<button type="submit">Submit</button>
</div>
}
執行:
F12->Network 檢視請求
可以看到,initiator 為XMLHttpRequest ,驗證了請求確實是Ajax。
分析Obstrusivejavascript 工作原理
<form action="/People/GetPeoplePartial" data-ajax="true" data-ajax-mode="replace" data-ajax-update="#tableBody" id="form0" method="post">
這是MVC Framework生成的form tag,對於unobsrutive javascript 來說,他關心的是data-ajax=”true”和data-ajax開頭的attribute,首先找到所有data-ajax=”true”的form,然後根據data-ajax-mode找到data-ajax-update的id(注意,unobstrusivejs 基於Jquery,需要加#)完成區域性重新整理。
Ajax Options
以下列出一些常用的AjaxOptions :
Confirm |
發起請求前彈出確認框,指定確認框的文字 |
HttpMethod |
請求型別:POST,GET,PUT,DELETE等等 |
InsertionMode |
Replace,Before,After, 預設為Replace |
LoadingElementId |
請求發出後,收到Server迴應前彈出一個loading的div,這裡指定div id |
LoadingElementDuration |
設定loading Div最多顯示多少秒 |
UpdateTargetId |
要區域性更新的container id |
Url |
發請求的url |
Loading 和Confirmation
現在稍作改動,給例子加一個Confirmation和loading
準備loading的div和css
Css:
<style type="text/css">
.popup_background {
z-index: 10;
background-color: grey;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
opacity: 0.4;
}
.popup_loading {
z-index: 11;
font-size: 50px;
top: 400px;
left: 600px;
position: absolute;
}
</style>
僅作為演示,我hard-code了loading div的位置,實際專案中需要調整
Html:
<div id="loading" class="popup_background" style="display:none">
<div class="popup_loading">
<p>Loading...</p>
</div>
</div>
在AjaxOption中指定Id
var ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody" ,
Confirm = "Sure?",
LoadingElementDuration = 2000,
LoadingElementId = "loading"
};
在Controller中模擬一個長時間的任務
Sleep 3秒
private void MockLongTimeProcessing()
{
Thread.Sleep(3000);
}
在partialview中呼叫一下
public PartialViewResult GetPeoplePartial(string selectedRole ="All")
{
MockLongTimeProcessing();
...
}
執行,檢視效果:
Ajax連結
Ajax連結的生成很簡單。
稍作改動,看一下ajax連結的使用方法,在View(AjaxList.cshtml)中新增:
<div>
@foreach (string role in Enum.GetNames(typeof(Role))) {
<div class="ajaxLink">
@Ajax.ActionLink(role,"GetPeoplePartial",
new {selectedRole= role},
ajaxOpts)
</div>
}
</div>
這樣就可以了,其實就是呼叫Ajax.ActionLink函式,設定連結的文字,Action,以及引數,最後一個是AjaxOption,我們用的是前面一個demo的。
新增對Json的支援
改動Controller
和前面的步驟一樣,新增兩個Action,一個是服務第一次載入頁面的 請求,我們返回View,一個是Ajax過來的,我們需要返回JsonResult:
public ActionResult JsonList()
{
return View("JsonList");
}
public JsonResult GetPeopleJson(string selectedRole = "All")
{
IEnumerable<Person> data = _personData;
if (selectedRole !="All")
{
var selected =(Role)Enum.Parse(typeof(Role), selectedRole);
data =_personData.Where(p => p.Role == selected);
}
return Json(data,JsonRequestBehavior.AllowGet);
}
新增View:
JsonList.cshtml
@using MVCAjax.Models
@model string
@{
ViewBag.Title = "GetPeople";
var ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody",
};
}
<script type="text/javascript">
function processData(data) {
var target =$("#tableBody");
target.empty();
for (var i = 0; i <data.length; i++) {
var person = data[i];
target.append("<tr><td>" + person.FirstName +"</td><td>"
+ person.LastName +"</td><td>" + person.Role +"</td></tr>");
}
}
</script>
<h2>Get Json List</h2>
<table>
<thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
<tbody id="tableBody">
@Html.Action("GetPeoplePartial", new {selectedRole = Model })
</tbody>
</table>
<div>
@foreach (string role in Enum.GetNames(typeof(Role))) {
<div class="ajaxLink">
@Ajax.ActionLink(role, "GetPeople",
new {selectedRole = role},
new AjaxOptions {
Url = Url.Action("GetPeopleJson", new {selectedRole = role}),
OnSuccess = "processData"
})
</div>
}
</div>
為了簡便演示,僅僅展示Json部分,筆者拿掉了Loading和Confirm的部分。
程式碼分析
程式碼的核心在於OnSuccess = "processData" 。
當Ajax請求成功時,指向processData函式,在這個函式裡面,我們拿到id(JqueryId)為#tableBody的表單,清空,手動拼html,並用jquery新增到這個html control中。這部分可以優化,可以選擇handlebar.js,knockout.js 等js template。
在table body中呼叫了@Html.Action("GetPeoplePartial",new {selectedRole = Model }),和前面的原因一樣,為了第一次載入時顯示出所有人員列表。
另外,AjaxOptions中還有其他Callback型別;
OnBegin : 發請求前
OnFailure :請求失敗
OnSuccess :請求成功
OnComplete :請求完畢
相關文章
- Asp.Net MVC4 系列--進階篇之ViewASP.NETMVCView
- Asp.Net MVC4 系列--進階篇之Model(1)ASP.NETMVC
- Asp.Net MVC4 系列--進階篇之Model(2)ASP.NETMVC
- Asp.Net MVC4系列--進階篇之Helper(1)ASP.NETMVC
- Asp.Net MVC4 系列--進階篇之Helper(2)ASP.NETMVC
- Asp.Net MVC4 系列--進階篇之Controller(2)ASP.NETMVCController
- Asp.Net MVC4 系列-- 進階篇之路由(1)ASP.NETMVC路由
- Asp.Net MVC4 系列--進階篇之路由 (2)ASP.NETMVC路由
- Asp.Net MVC 系列--進階篇之FilterASP.NETMVCFilter
- Asp.Net MVC系列--進階篇之controller(1)ASP.NETMVCController
- Asp.Net MVC4 系列--基礎篇(1)ASP.NETMVC
- Asp.Net MVC4系列---基礎篇(5)ASP.NETMVC
- Asp.Net MVC4系列---基礎篇(4)ASP.NETMVC
- 【webpack 系列】進階篇Web
- JS進階系列 --- ajax請求優化JS優化
- ASP.NET MVC 之 AJAXASP.NETMVC
- web系列之AjaxWeb
- .NET進階系列之四:深入DataTable
- 帶你深度解鎖Webpack系列(進階篇)Web
- 正規表示式系列之中級進階篇
- Java多執行緒之進階篇Java執行緒
- Membership三步曲之進階篇
- 前端進階(三)從0到1學AJAX,這篇就夠了!前端
- Java進階篇 設計模式之十四 ----- 總結篇Java設計模式
- to debug asp.net mvc4ASP.NETMVC
- 你所不知道的ASP.NET Core進階系列(三)ASP.NET
- create table進階學習系列(十一)之cluster
- Linux ACL 許可權之進階篇Linux
- Dagger 2 系列(五) -- 進階篇:@Scope 和 @Singleton
- ASP.NET 的MVC結構之AJAXASP.NETMVC
- ASP.NET進階:認清控制元件 之 Button (轉)ASP.NET控制元件
- 高階前端進階系列 - webview前端WebView
- [一天一個進階系列] - MyBatis基礎篇MyBatis
- Three.js進階篇之6 - 碰撞檢測JS
- Three.js進階篇之5 - 粒子系統JS
- React進階篇1React
- React進階篇2React
- 進階篇_vector容器