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 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>
接下來,我們針對每個細部,做一個講解,有講不好的地方,不要鞭我喔><。
清空
我們的第一個function,主要用途是清除status的資訊,在HTML裡面,有一段會顯示錯誤訊息等資訊,所以我們這邊也要準備一下,清除這些資訊的Function。
//清空status區段 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。
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(); } } }); }
這樣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://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://blog.kkbruce.net/search/label/Web%20API#.T70ecMWYS48 "http://blog.kkbruce.net/search/label/Web%20API#.T70ecMWYS48")
- [http://mvc.keigen.net/2012/03/web-api_30.html](http://mvc.keigen.net/2012/03/web-api_30.html "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](http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations "http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations")