[ASP.NET][MVC] ASP.NET MVC (10) : 部份檢視與 AJAX 的整合

我們在前一篇文章中看到部份檢視的功能,它除了可以作為網頁上的排版外,其實它還有一個更重要的用途:與 AJAX 結合。ASP.NET MVC 本身的 AJAX 目前可支援最早的,以 MicrosoftAjax.js 與 MicrosoftMvcAjax.js 組成的 AJAX,以及由 MVC 3.0 開始支援的 jquery.min.js 與 jquery.unobtrusive-ajax.js 兩種,要選擇哪一種是由開發人員自己決定,但個人推薦使用 jQuery 的 ajax,一來方便,二來可相容於許多的 jQuery Plug-ins,甚至想用 jQuery Mobile 來開發行動網頁,也可以享受到 MVC AJAX 的能力。

我們在前一篇文章中看到部份檢視的功能,它除了可以作為網頁上的排版外,其實它還有一個更重要的用途:與 AJAX 結合。ASP.NET MVC 本身的 AJAX 目前可支援最早的,以 MicrosoftAjax.js 與 MicrosoftMvcAjax.js 組成的 AJAX,以及由 MVC 3.0 開始支援的 jquery.min.js 與 jquery.unobtrusive-ajax.js 兩種,要選擇哪一種是由開發人員自己決定,但個人推薦使用 jQuery 的 ajax,一來方便,二來可相容於許多的 jQuery Plug-ins,甚至想用 jQuery Mobile 來開發行動網頁,也可以享受到 MVC AJAX 的能力。

首先,我們在 MyController 中加入兩個方法,一個是進入點,一個是給 AJAX 呼叫的程式:


public ActionResult CustomerDetailView()
{
    var customer = Models.CustomerDataContext.LoadCustomers();

    ViewData["index"] = 0;

    if (customer.Count() == 0)
        return View();
    else
        return View(customer.First());
}

public ActionResult DetailPartialView(int? position)
{
    if (position == null)
        position = 0;

    var customer = Models.CustomerDataContext.LoadCustomers();

    if (customer.Count() == 0)
        return new HttpNotFoundResult();
    else
    {
        ViewData["index"] = position.Value;
        customer.Sort(new Comparison<Models.Customer>((c1, c2) => c1.CustomerID.CompareTo(c2.CustomerID)));
        return PartialView(customer[position.Value]);
    }
}

這段程式碼是展示依順序瀏覽客戶資料的功能,所以在 DetailPartialView 中有實作一個排序的功能,不過那個不是重點,重要的是它會回傳 PartialView,並且將該位置所在的 Model (Customer) 交給該 PartialView,而這個 PartialView 就是 ~/Views/My/DetailPartialView.cshtml:


@model MvcApplication1.Models.Customer
<ul>
    <li>ID: @this.Model.CustomerID</li>
    <li>Company Name: @this.Model.CompanyName</li>
    <li>Contactor Name: @this.Model.ContactName</li>
    <li>Contactor Title: @this.Model.ContactTitle</li>
    <li>Address: @this.Model.Country @this.Model.City @this.Model.Address</li>
    <li>Phone: @this.Model.Phone</li>
    <li>Fax: @this.Model.Fax</li>
    <li>Region: @this.Model.Region</li>
</ul>

@Ajax.ActionLink("Next", "DetailPartialView",
                 new { position = Convert.ToInt32(ViewData["index"]) + 1 },
                 new AjaxOptions { UpdateTargetId = "customerPanel" })

在 DetailViewPartial.cshtml 中,主要是顯示每筆 Customer 的資訊,而在最下方的 @Ajax.ActionLink(),會產生給 jQuery 看的指令碼,它產生的會是這樣的 HTML:


<a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#customerPanel" href="/My/DetailPartialView?position=1">Next</a>

接著,建立 ~/My/CustomerDetailView.cshtml,並一樣加入下列指令:


@model MvcApplication1.Models.Customer
@{
    ViewBag.Title = "CustomerDetailView";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
    CustomerDetailView</h2>
<div id="customerPanel">
    @if (this.Model != null)
    {
        <ul>
            <li>ID: @this.Model.CustomerID</li>
            <li>Company Name: @this.Model.CompanyName</li>
            <li>Contactor Name: @this.Model.ContactName</li>
            <li>Contactor Title: @this.Model.ContactTitle</li>
            <li>Address: @this.Model.Country @this.Model.City @this.Model.Address</li>
            <li>Phone: @this.Model.Phone</li>
            <li>Fax: @this.Model.Fax</li>
            <li>Region: @this.Model.Region</li>
        </ul>
        
        @Ajax.ActionLink("Next", "DetailPartialView",
                 new { position = Convert.ToInt32(ViewData["index"]) + 1 },
                 new AjaxOptions { UpdateTargetId = "customerPanel" })
    }
</div>

(註,這裡還可以改的更好,例如不用重覆呈現 PartialView 內的內容,不過作法就留給你練習 :) )

最後,在 ~/Views/Shared/_layout.cshtml 中,把 AJAX 的 driver 加進去,也就是 jquery.min.js 與 jquery.unobtrusive-ajax.js:


<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

完成後,瀏覽 http://[root]/My/CustomerDetailView,可以看到這樣的內容:

image

然後按 Next,可以看到不同的資料,但會發現瀏覽器並沒有引發 refresh:

image

 

Reference:

http://www.atlanticbt.com/blog/asp-net-mvc-using-ajax-json-and-partialviews/
http://stackoverflow.com/questions/5725525/asp-net-mvc-3-razor-ajax-actionlink-what-am-i-doing-wrong
http://www.asp.net/mvc/tutorials/contact-manager/iteration-7-add-ajax-functionality-cs