ASP.NET MVC Web API - 利用jQuery進行CRUD! (三) View篇
支援版本
- ASP.NET MVC 4 Beta
終於進入到View篇了,本來是預計一天把三篇寫完的,結果沒想到變成一個禮拜一篇= =,現在終於知道連載的辛苦了,富木堅,對不起以前都一直罵你XDD;回到主題,上一篇我們介紹到Controller,也把整個Web Service完成了,但是我們還沒講到要怎樣利用JavaScript ( 利用jQuery這個函式庫 )對Web Service進行呼叫阿!?所以我們這篇來談談View的部分。
jQuery
小弟就不再這邊詳細的介紹jQuery了,我相信很多人應該都會使用,這邊只簡單的介紹一下jQuery是做甚麼的;jQuery 是一個非常方便,快速,程式碼又簡潔的JavaScript函式庫,原本我們用JavaScript來進行DOM物件的尋找、處理事件、動畫、瀏覽器版本還有Ajax等等,都會寫非常多的程式碼,所以就有位天才John Resig,寫了jQuery來大幅的簡化,總之,就是一個好物就是了;如果不會jQuery,可以參考一下jQuery的官網或是暗黑前輩的超完整教學,所以這部分小弟就不多介紹嚕。
Knockout
這裡必須還要再提一個東西,就是Knockout,他也是一個JavaScript的程式庫,不過不用擔心,小弟沒那麼慘忍XDD,一下要K Repository Patten,一下要看ASP.NET MVC Web API,一下又要看jQuery,所以這篇文章小弟不會用到Knockout;但為什麼要提到這個呢!?那是因為目前這個東西也正是被納入到ASP.NET MVC裡面,而且官方的範例中,就是大量地使用到這個程式庫,Knockout主要的用處是利用MVVM模式,來繫節畫面上的UI;詳細可以參考暗黑前輩的Knockout這篇文章,或是官網,或是Andy前輩的FAQ Book;不過在一次的重申,這篇文章不會用到Knockout,所以可以放鬆心情的去讀這幾位前輩的文章=v=。
View
前面鋪完路後,我們終於要正式開始撰寫View了,不知道大家還記不記得,第一章的時候,那個空白的圖?那時候我們建立起View後,並沒有在View裡面添加甚麼,現在我們終於要開始加上一些東西了;首先,我們可以先打開如下圖的檔案,這就是我們第一章就準備好的檔案。
我們首先先準備一下畫面,我們預期的畫面如下圖,基本上和官網的差不多 ( 官網範例沒有Delete喔XDD )。
HTML
接下來,HTML要怎樣寫哩,其實也沒甚麼特別的,就是利用了一些HTML5的標籤 ( 畢竟已經是HTML5的時代了 ),然後準備好一個Table,來顯示資料,並且準備一些輸入欄位,以便後續的CRUD( 這裡範例是用DIV標籤來包輸入欄位,當然也可以用DD、DT、或是li等標籤,看個人喜好吧 ),當然,我們也要準備一些 Button來觸發事件,所以我們準備了很多的Button ( 不是Submit按鈕喔!!兩個是有差異的。 ),來觸發各種事件,完成大致上如下。( 眼力好的人,可能已經會發現Button裡面已經有寫準備觸發的事件的Function名稱了,我們等下就會把這些Function建立起來了喔! )
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div id="body">
<section class="content-wrapper main-content">
<h3>Contacts</h3>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Phone</th>
</tr>
</thead>
<tbody id="customers">
</tbody>
</table>
</section>
<section id="detail" class="content-wrapper">
<h3>View Contact</h3>
<label for="contactId">ID</label>
<input type="text" title="ID" id="contactId" size="5" />
<input type="button" value="Get" onclick="find();" />
<div>
<label for="name">Name</label>
<input type="text" title="Name" id="name" />
</div>
<div>
<label for="phone"> Phone</label>
<input type="text" title="Phone" id="phone" />
</div>
<div>
<input type="button" value="Update" onclick="update();" />
<input type="button" value="Delete" onclick="del();" />
<input type="button" value="Add New" onclick="add();" />
</div>
<div>
<p id="status"></p>
</div>
</section>
</div>
</body>
</html>
接下來,我們稍微弄一下美化吧,所以我們利用CSS進行美化,( 再次強調,不要用HTML做為美化的工具,美化的職責應該是由CSS負責的喔!! )。
CSS
好,不用擔心,我們沒有用到CSS3,下面是個很簡單的CSS,把CSS放到head標籤底下;CSS的內容也超簡單,基本上也只是把table、tr、th、td上個顏色,畢竟小弟現在不是要寫CSS的筆記,所以稍微設定一下而已;另外,小弟特別把從頭擷取index.cshtml的程式碼,我想這樣大家會比較了解CSS要放到哪邊。
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <style type="text/css"> table { border: 1px solid #000; border-collapse: collapse; color: #666666; min-width: 200px; } tr { border: 1px solid #000; line-height: 25px; } th { background-color: #B1C3CC; color: #000; font-size: 13px; text-align: left; } th, td { padding-left: 5px; } </style> </head>
完成後,就會變成這樣,有沒有有沒有,變漂亮了吧!!( 好吧,其實也沒漂亮到哪去…但我們這篇的重點是jQuery和Web Service,小細節就不要計較了XDD)。
JavaScript & jQuery
好,完成畫面後,就可以隨便亂點了,然後就會在偵錯工具出現這些錯誤( 記得偵錯工具要打開…),這當然很正常,因為我們JavaScript還沒開始寫嘛。
接下來我們開始寫JavaScript,以下是整個JavaScript,我們可以把整個JavaScript放到head標籤裡面,我們後面會針對細節做介紹。 ( 好的,我知道一些JavaScript放在head,效能等等之類的問題,但是,這不是我們這篇的重點=v= )
<script type="text/javascript">
//清空status區段
function clearStatus() {
$('#status').html('');
}
var API_URL = "api/Customer/";
//增加資料
function add() {
clearStatus();
var json = JSON.stringify({ name: $("#name").val(), phone: $("#phone").val() });
$.ajax({
url: API_URL,
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: json,
statusCode: {
201 /*Created*/: function (data) {
getAll();
}
}
});
}
//尋找資料
function find() {
clearStatus();
var id = $('#contactId').val();
if (id != "") {
$.getJSON(API_URL + id,
function (data) {
$("#customers tr").remove();
$("#customers").append("<tr>" +
"<td>" + data["Id"] + "</td>" +
"<td>" + data["Name"] + "</td>" +
"<td>" + data["Phone"] + "</td>" +
"</tr>");
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
} else {
getAll();
}
}
//更新資料
function update() {
clearStatus();
var id = $('#contactId').val();
var json = JSON.stringify({ name: $("#name").val(), phone: $("#phone").val() });
$.ajax({
url: API_URL + id,
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: json,
success: function () { getAll(); }
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
//刪除指定資料
function del() {
clearStatus();
var id = $('#contactId').val();
$.ajax({
url: API_URL + id,
cache: false,
type: 'DELETE',
contentType: 'application/json; charset=utf-8',
//data: json,
success: function () { getAll(); }
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
//取得所有資料
function getAll() {
clearStatus();
//利用Get方式取得。
$.getJSON(API_URL,
function (data) {
$("#customers tr").remove();
for (i = 0; i < data.length; i++) {
$("#customers").append("<tr>" +
"<td>" + data[i].Id + "</td>" +
"<td>" + data[i].Name + "</td>" +
"<td>" + data[i].Phone + "</td>" +
"</tr>");
}
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
//開始時,先把資料讀取進來
$(document).ready(function () {
getAll();
});
</script>
接下來,我們針對每個細部,做一個講解,有講不好的地方,不要鞭我喔><。
清空
我們的第一個function,主要用途是清除status的資訊,在HTML裡面,有一段會顯示錯誤訊息等資訊,所以我們這邊也要準備一下,清除這些資訊的Function。
function clearStatus() {
$('#status').html('');
}
接下來繼續。
取得全部
我們先來介紹取得全部的這個Funciton,也就是getAll(),我們這邊利用jQuery的getJSON API進行處理,這個API預設會用HTTP的GET命令;當順利取得資料的時候,就會把HTML table裡面的東西移除掉,然後再利用迴圈的方式,把取得的JSON資料和HTML標籤td,一起塞到Table裡面去。
function getAll() {
clearStatus();
//利用Get方式取得。
$.getJSON(API_URL,
function (data) {
$("#customers tr").remove();
for (i = 0; i < data.length; i++) {
$("#customers").append("<tr>" +
"<td>" + data[i].Id + "</td>" +
"<td>" + data[i].Name + "</td>" +
"<td>" + data[i].Phone + "</td>" +
"</tr>");
}
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
然後我們來看看新增。
ADD
第二段我們要講的是ADD,但我們談論ADD之前,我們要先設一個變數,負責記錄網址位置,也就是API_URL;接下來,因為是新增,所以我們會需要準備傳遞資料,所以我們利用JSON.stringify來將我們填入表單的資料,轉成JSON格式。然後我們就要利用jQuery的ajax API來對Web Service進行呼叫;還記得嗎?HTTP的POST就是新增的意思,所以我們Type會設定POST,並且等傳回201時,執行getAll()這個Function。
//增加資料
function add() {
clearStatus();
var json = JSON.stringify({ name: $("#name").val(), phone: $("#phone").val() });
$.ajax({
url: API_URL,
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: json,
statusCode: {
201 /*Created*/: function (data) {
getAll();
}
}
});
}
這樣ADD就完成了,下圖是執行結果,我們填入AA、AA的資料 ( Phone欄位沒有驗證,我真的知道><,是我的錯。 ),按下AddNew後,畫面會自動更新Table,出現第四筆資料;而下面的分析工具可以看到,真的送出了POST。
Find
接下來是尋找資料,其實尋找資料和getAll()很像,就不多加敘述了,但比較特別的是,我們會在網址 (API_URL)後面加上id,來尋找到想要找到的那一筆;如果沒有找到,就會在status區塊報錯。
function find() {
clearStatus();
var id = $('#contactId').val();
if (id != "") {
$.getJSON(API_URL + id,
function (data) {
$("#customers tr").remove();
$("#customers").append("<tr>" +
"<td>" + data["Id"] + "</td>" +
"<td>" + data["Name"] + "</td>" +
"<td>" + data["Phone"] + "</td>" +
"</tr>");
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
} else {
getAll();
}
}
執行結果如下,table會更新成尋到到的那筆,在下面的偵錯視窗可以看到,利用了Get。
Update
更新資料和新增資料很像,一樣是利用JSON.stringify來轉換成JSON格式,然後用PUT來進行傳送。
function update() {
clearStatus();
var id = $('#contactId').val();
var json = JSON.stringify({ name: $("#name").val(), phone: $("#phone").val() });
$.ajax({
url: API_URL + id,
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: json,
success: function () { getAll(); }
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
執行結果如下,我們ID、Name、Phone都填好後,按下Update就會更新資料,並且取得最新的table,我們也可以看到下面的偵錯工具,可以發現到現在是用HTTP PUT命令。
Delete
刪除資料更簡單了,因為連JSON都不需要了,我們只要URL配合id,並且送出DELETE的指令就可以了!
function del() {
clearStatus();
var id = $('#contactId').val();
$.ajax({
url: API_URL + id,
cache: false,
type: 'DELETE',
contentType: 'application/json; charset=utf-8',
//data: json,
success: function () { getAll(); }
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
測試一下,我們填入要刪除的ID,並按下Delete按鈕,table就會自動更新,我們也可以從偵錯視窗看到目前使用的是HTTP裡面的Delete命令。
畫面載入完成時
這是最後一小段的程式碼,小弟我希望畫面載入完成後,table會再動載入資料進來,所以加了這段。
$(document).ready(function () {
getAll();
});
到這邊就大功告成,我們最後再把整個index.cshtml看一遍吧。
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<style type="text/css">
table
{
border: 1px solid #000;
border-collapse: collapse;
color: #666666;
min-width: 200px;
}
tr
{
border: 1px solid #000;
line-height: 25px;
}
th
{
background-color: #B1C3CC;
color: #000;
font-size: 13px;
text-align: left;
}
th, td
{
padding-left: 5px;
}
</style>
<script src="@Url.Content("~/Scripts/jquery-1.6.2.js")" type="text/javascript"></script>
<script type="text/javascript">
//清空status區段
function clearStatus() {
$('#status').html('');
}
var API_URL = "api/Customer/";
//增加資料
function add() {
clearStatus();
var json = JSON.stringify({ name: $("#name").val(), phone: $("#phone").val() });
$.ajax({
url: API_URL,
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: json,
statusCode: {
201 /*Created*/: function (data) {
getAll();
}
}
});
}
//尋找資料
function find() {
clearStatus();
var id = $('#contactId').val();
if (id != "") {
$.getJSON(API_URL + id,
function (data) {
$("#customers tr").remove();
$("#customers").append("<tr>" +
"<td>" + data["Id"] + "</td>" +
"<td>" + data["Name"] + "</td>" +
"<td>" + data["Phone"] + "</td>" +
"</tr>");
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
} else {
getAll();
}
}
//更新資料
function update() {
clearStatus();
var id = $('#contactId').val();
var json = JSON.stringify({ name: $("#name").val(), phone: $("#phone").val() });
$.ajax({
url: API_URL + id,
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: json,
success: function () { getAll(); }
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
//刪除指定資料
function del() {
clearStatus();
var id = $('#contactId').val();
$.ajax({
url: API_URL + id,
cache: false,
type: 'DELETE',
contentType: 'application/json; charset=utf-8',
//data: json,
success: function () { getAll(); }
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
//取得所有資料
function getAll() {
clearStatus();
//利用Get方式取得。
$.getJSON(API_URL,
function (data) {
$("#customers tr").remove();
for (i = 0; i < data.length; i++) {
$("#customers").append("<tr>" +
"<td>" + data[i].Id + "</td>" +
"<td>" + data[i].Name + "</td>" +
"<td>" + data[i].Phone + "</td>" +
"</tr>");
}
})
.fail(
function (xhr, textStatus, err) {
$('#status').html('Error: ' + err);
});
}
//開始時,先把資料讀取進來
$(document).ready(function () {
getAll();
});
</script>
</head>
<body>
<div id="body">
<section class="content-wrapper main-content">
<h3>Contacts</h3>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Phone</th>
</tr>
</thead>
<tbody id="customers">
</tbody>
</table>
</section>
<section id="detail" class="content-wrapper">
<h3>View Contact</h3>
<label for="contactId">ID</label>
<input type="text" title="ID" id="contactId" size="5" />
<input type="button" value="Get" onclick="find();" />
<div>
<label for="name">Name</label>
<input type="text" title="Name" id="name" />
</div>
<div>
<label for="phone"> Phone</label>
<input type="text" title="Phone" id="phone" />
</div>
<div>
<input type="button" value="Update" onclick="update();" />
<input type="button" value="Delete" onclick="del();" />
<input type="button" value="Add New" onclick="add();" />
</div>
<div>
<p id="status"></p>
</div>
</section>
</div>
</body>
</html>
以上,終於寫完!
後記
寫完的當下,才發現KingKong前輩,和阿源哥哥前輩都有寫過類似的文章 ( 暈倒 ),但不管怎樣,這是小弟自己邊看邊寫的讀書筆記啦><,所以如果小弟沒寫好的地方,也可以去看看前輩們寫的超詳細文章喔!!
參考資料
- http://zh.wikipedia.org/wiki/JQuery
- http://jquery.com/
- http://blog.darkthread.net/post-2009-01-23-my-jquery-tutorial.aspx
- http://knockoutjs.com/
- http://blog.darkthread.net/post-2012-05-09-knockout-js-intro.aspx
- http://blog.faq-book.com/?p=3456
- http://blog.kkbruce.net/search/label/Web%20API#.T70ecMWYS48
- http://mvc.keigen.net/2012/03/web-api_30.html
- http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations