使用 AJAX 傳送動態更新
由 Microsoft 提供
這是免費的 "NerdDinner" 應用程式教學課程的第 10 個步驟,詳細介紹了如何使用 ASP.NET MVC 1 建置一個小型但完整的 Web 應用程式。
步驟 10 使用整合在 Dinner 詳細資料頁面中的基於 Ajax 的方法,實現對登入使用者的支援,以回應他們參加 Dinner 的興趣 ...
如果使用 ASP.NET MVC 3,建議遵循 MVC 3 使用者入門或 MVC Music 市集教學課程。
NerdDinner 步驟 10:啟用 RSVP 接受的 AJAX
現在讓我們實作對已登入使用者的支援,以便他們可以回覆有興趣參加 Dinner。 我們將使用整合在 Dinner 詳細資料頁面中的 AJAX 方法來啟用此功能。
指示使用者是否已回覆參加。
使用者可以造訪 /Dinners/Details/[id] URL,以查看特定 Dinner 的詳細資料:
Details() 動作方法的實作如下:
//
// GET: /Dinners/Details/2
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View(dinner);
}
實現回覆支援的第一步是在我們的 Dinner 物件中新增一個 IsUserRegistered(username) 協助程式方法 (在我們之前建立的 Dinner.cs 部分類別中)。 此協助程式方法根據使用者目前是否已回覆 Dinner 來返回 true 或 false:
public partial class Dinner {
public bool IsUserRegistered(string userName) {
return RSVPs.Any(r => r.AttendeeName.Equals(userName, StringComparison.InvariantCultureIgnoreCase));
}
}
然後,我們可以將下列程式碼新增至 Details.aspx 檢視範本,以顯示指出使用者是否已註冊該事件的適當訊息:
<% if (Request.IsAuthenticated) { %>
<% if (Model.IsUserRegistered(Context.User.Identity.Name)) { %>
<p>You are registred for this event!</p>
<% } else { %>
<p>You are not registered for this event</p>
<% } %>
<% } else { %>
<a href="/Account/Logon">Logon</a> to RSVP for this event.
<% } %>
現在,當使用者造訪他們註冊的 Dinner 時,就會看到此訊息:
當他們造訪沒有註冊的 Dinner 時,他們不會看到此訊息:
實作註冊動作方法
現在讓我們新增必要的功能,以便使用者可以從詳細資料頁面回覆 Dinner。
為了實作此動作,我們將以滑鼠右鍵按一下 \Controllers 目錄並選擇新增 -> 控制器功能表命令,以建立新的 “RSVPController” 類別。
我們將在新的 RSVPController 類別內實作 [註冊] 動作方法,該方法將 Dinner 的識別碼作為引數、擷取適當的 Dinner 物件、檢查已登入的使用者目前是否在已註冊的使用者清單中,如果沒有為其新增 [回覆] 物件:
public class RSVPController : Controller {
DinnerRepository dinnerRepository = new DinnerRepository();
//
// AJAX: /Dinners/RSVPForEvent/1
[Authorize, AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsUserRegistered(User.Identity.Name)) {
RSVP rsvp = new RSVP();
rsvp.AttendeeName = User.Identity.Name;
dinner.RSVPs.Add(rsvp);
dinnerRepository.Save();
}
return Content("Thanks - we'll see you there!");
}
}
請注意上面我們如何傳回一個簡單的字串作為動作方法的輸出。 我們本可以將這條訊息內嵌到檢視範本,但由於它非常簡短,我們將直接使用控制器基底類別上的 Content() 協助程式方法,並返回像上面那樣的字串訊息。
使用 AJAX 呼叫 RSVPForEvent 動作方法
我們將使用 AJAX 從 [詳細資料] 檢視叫用 [註冊] 動作方法。 實作這項操作相當簡單。 首先,我們將新增兩個指令碼程式庫參考:
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
第一個程式庫會參考核心 ASP.NET AJAX 用戶端指令碼程式庫。 此檔案的大小約為 24k (壓縮),且包含核心用戶端 AJAX 功能。 第二個程式庫包含與 ASP.NET MVC 內建 AJAX 協助程式方法整合的公用程式函式 (我們很快就會使用此方法)。
然後,我們可以更新稍早新增的檢視範本程式碼,這樣就不會輸出「您未註冊此事件」訊息,而是轉譯連結,在推送時執行 AJAX 呼叫,以在 [回覆控制器] 叫用 RSVPForEvent 動作方法並回覆使用者:
<div id="rsvpmsg">
<% if(Request.IsAuthenticated) { %>
<% if(Model.IsUserRegistered(Context.User.Identity.Name)) { %>
<p>You are registred for this event!</p>
<% } else { %>
<%= Ajax.ActionLink( "RSVP for this event",
"Register", "RSVP",
new { id=Model.DinnerID },
new AjaxOptions { UpdateTargetId="rsvpmsg"}) %>
<% } %>
<% } else { %>
<a href="/Account/Logon">Logon</a> to RSVP for this event.
<% } %>
</div>
上述使用的 Ajax.ActionLink() 協助程式方法內建於 ASP.NET MVC,而且類似於 Html.ActionLink() 協助程式方法,不同之處在於,它不會執行標準導覽,而是在按一下連結時對動作方法發出 AJAX 呼叫。 在上方,我們會在 [回覆] 控制器上呼叫 [註冊] 動作方法,並將 DinnerID 當做 "id" 參數傳遞給它。 我們傳遞的最後 AjaxOptions 參數表示我們想要取得動作方法傳回的內容,並在識別碼為 “rsvpmsg” 的頁面上更新 HTML <div> 項目。
現在當尚未註冊的使用者瀏覽至 Dinner 時,他們會看到 [回覆] 的連結:
如果他們按一下 [此事件的回覆] 連結,他們會對 [回覆] 控制器上的 [註冊] 動作方法進行 AJAX 呼叫,並在完成時看到更新的訊息,如下所示:
進行此 AJAX 呼叫時所涉及的網路頻寬和流量非常輕量。 當使用者按一下 [回覆此事件] 連結時,會向 /Dinners/Register/1 URL 發送一個小型的 HTTP POST 網路要求,如下所示:
POST /Dinners/Register/49 HTTP/1.1
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Referer: http://localhost:8080/Dinners/Details/49
而我們的 [註冊] 動作方法的回應只是:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 29
Thanks - we'll see you there!
這個輕量型的呼叫速度很快,即使網路速度慢也能正常工作。
新增 jQuery 動畫
我們實作的 AJAX 功能運作良好且快速。 不過,有時候會發生如此快的情況,使用者可能不會注意到 [回覆] 連結已被新的文字取代。 為了讓結果更加明顯,我們可以新增簡單的動畫來吸引人們對更新訊息的注意。
預設 ASP.NET MVC 專案範本包含 jQuery – 一個出色且非常受歡迎的開放原始碼 JavaScript 程式庫,Microsoft 也提供支援。 jQuery 提供許多功能,包括很好的 HTML DOM 選取和效果程式庫。
若要使用 jQuery,我們會先新增指令碼參考。 由於我們將在網站內的各種位置使用 jQuery,因此會在 Site.master 主版頁面檔案中新增指令碼參考,讓所有頁面都可以使用它。
<script src="/Scripts/jQuery-1.3.2.js" type="text/javascript"></script>
使用 JQuery 撰寫的程式碼通常會使用全域 "$()" JavaScript 方法,使用 CSS 選取器擷取一或多個 HTML 元素。 例如,$("#rsvpmsg") 會選取任何具有 rsvpmsg 識別碼的 HTML 元素,而$(".something") 會選取具有 “something” CSS 類別名稱的所有元素。 您也可以使用選取器查詢來撰寫更進階的查詢,例如 [傳回所有核取的選項按鈕],例如:$("input[@type=radio][@checked]")。
選擇元素後,您可以呼叫它們的方法來執行操作,例如隱藏它們:$("#rsvpmsg").hide();
在我們的 [回覆] 案例中,我們將定義名為 “AnimateRSVPMessage” 的簡單 JavaScript 函式,以選取 “rsvpmsg” <div> 並建立其文字內容大小的動畫。 下列程式碼會啟動小型文字,然後使其在 400 毫秒的時間範圍內變大:
<script type="text/javascript">
function AnimateRSVPMessage() {
$("#rsvpmsg").animate({fontSize: "1.5em"},400);
}
</script>
然後,我們可以在 AJAX 呼叫順利完成之後,連接此 JavaScript 函式,方法是將其名稱傳遞至 Ajax.ActionLink() 協助程式方法 (透過 AjaxOptions “OnSuccess” 事件屬性):
<%= Ajax.ActionLink( "RSVP for this event",
"Register", "RSVP",
new { id=Model.DinnerID },
new AjaxOptions { UpdateTargetId="rsvpmsg",
OnSuccess="AnimateRSVPMessage"}) %>
現在,按一下 [回覆此事件] 連結,且我們的 AJAX 呼叫成功完成時,傳回的內容訊息將會以動畫顯示並變大:
除了提供 "OnSuccess" 事件之外,AjaxOptions 物件也會公開您可以處理的 OnBegin、OnFailure 和 OnComplete 事件 (以及其他各種屬性和實用選項)。
清除 - 重構回覆部分檢視
我們的詳細資料檢視範本開始有點長,隨著時間的推移,它會變得有點難以理解。 為了幫助提高程式碼的可讀性,讓我們最後建立一個部分視圖 RSVPStatus.ascx,它封裝了我們 [詳細資料] 頁面的所有 [回覆] 檢視程式碼。
我們可以在 \Views\Dinners 資料夾上按一下滑鼠右鍵,然後選擇新增 -> 檢視功能表命令來執行這項操作。 我們將採用 Dinner 物件作為其強型別 ViewModel。 然後,我們可以從 Details.aspx 檢視複製/貼上 [回覆] 內容。
一旦完成,我們也會建立另一個部分檢視 – EditAndDeleteLinks.ascx ,它封裝我們的 [編輯] 和 [刪除] 連結檢視程式碼。 我們也會將 Dinner 物件當作其強型別 ViewModel,並從 Details.aspx 檢視複製/貼上 [編輯] 和 [刪除] 邏輯。
然後,我們的詳細資料檢視範本就可以在底部包含兩個 Html.RenderPartial() 方法呼叫:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent"runat="server">
<%= Html.Encode(Model.Title) %>
</asp:Content>
<asp:Content ID="details" ContentPlaceHolderID="MainContent" runat="server">
<div id="dinnerDiv">
<h2><%=Html.Encode(Model.Title) %></h2>
<p>
<strong>When:</strong>
<%=Model.EventDate.ToShortDateString() %>
<strong>@</strong>
<%=Model.EventDate.ToShortTimeString() %>
</p>
<p>
<strong>Where:</strong>
<%=Html.Encode(Model.Address) %>,
<%=Html.Encode(Model.Country) %>
</p>
<p>
<strong>Description:</strong>
<%=Html.Encode(Model.Description) %>
</p>
<p>
<strong>Organizer:</strong>
<%=Html.Encode(Model.HostedBy) %>
(<%=Html.Encode(Model.ContactPhone) %>)
</p>
<% Html.RenderPartial("RSVPStatus"); %>
<% Html.RenderPartial("EditAndDeleteLinks"); %>
</div>
</asp:Content>
這可讓程式碼更清楚讀取和維護。
後續步驟
現在讓我們看看如何進一步使用 AJAX,並將互動式對應支援新增至應用程式。