今天去練習超多人的, 看著年輕一輩,突然覺得自己有點格格不入 ~_~
(好像該從Tricking退出了嗎)
Anyway, 每個禮拜天晚上的讀書會又開始了!
準備迎接接下來的挑戰!
2013年6月16日 星期日
2013年6月11日 星期二
[C#] WebApi 補充 : 設定媒體類型
在MVC4第一支Web Api 這篇文章有提到在 Global.asax 加入以下程式碼,
(或是加到「App_Start」→「WebApiConfig.cs」的Register函式)
可以由送出Http GET請求Url的參數決定預設回傳訊息的媒體類型:
//設定一個URL的新參數
//設定一個URL的新參數
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("json", "true", "application/json"));
//設定一個URL的新參數
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "text/xml"));
Example,
http://localhost:33855/api/Book?xml=true
Example,
http://localhost:33855/api/Book?xml=true
另外也可以在「App_Start」→「WebApiConfig.cs」的Register函式 加入以下程式碼,手動移除JSON或XML格式化程式,限制Web
Api只回應特定的媒體類型。
//移除回傳Json格式
config.Formatters.Remove(config.Formatters.JsonFormatter);
//移除回傳XML格式
config.Formatters.Remove(config.Formatters.XmlFormatter);
2013年6月7日 星期五
[C#] 使用HttpClient取得WebApi服務
使用HttpClient取得WebApi服務
JB
延續我們已經建立好的Book Web Api,
除了利用前端語法( 文章:使用jQuery取得WebApi服務 ) 去使用WebApi的CRUD方法。 我們也也可以使用新的HttpClient 使用Web Api。
※備註:
HttpClient 在VS2012 內建於System.Net.Http (v4.0.0.0) 中,但是如果要使用文章中的PutAsJsonAsync、PostAsJsonAsync等方法,必須加入HttpClientExtensions 這個參考,最快的方式是直接使用Nuget下載「MicrosoftASP.NET Web API Client Libraries」這個套件。
※備註:
HttpClient 在VS2012 內建於System.Net.Http (v4.0.0.0) 中,但是如果要使用文章中的PutAsJsonAsync、PostAsJsonAsync等方法,必須加入HttpClientExtensions 這個參考,最快的方式是直接使用Nuget下載「MicrosoftASP.NET Web API Client Libraries」這個套件。
2.
加入Windows Form/ WPF /Console程式專案都可以,名稱:ApiClient
4.
Book.cs
public class Book
{ public string ID { get; set; } public string NAME { get; set; } public Nullable<decimal> PRICE { get; set; } } |
5.
AppSetting.cs
在此類別建立HttpClient並設定它的基底位址等資訊。
在此類別建立HttpClient並設定它的基底位址等資訊。
public class ApiSetting : IDisposable
{ public static String API_URL = "http://localhost:33855/"; public static String ROUTE_URI = "api/Book/"; /// <summary> /// Create a HttpClient /// </summary> /// <returns></returns> public HttpClient CreateHttpClient() { //Intial HttpClient HttpClient API_CLIENT = new HttpClient(); //Set the http service uri API_CLIENT.BaseAddress = new Uri(ApiSetting.API_URL); //The http service is based on JSON format API_CLIENT.DefaultRequestHeaders.Accept.Add( new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); return API_CLIENT; } } |
6.
請記得在使用Web
Api服務前,先利用上面的ApiSetting建立一個HttpClient:
Get、Post、Put、Delect都是一樣,所以只列出一次在Get.cs 中 Initial HttpClient的程式碼。
Get、Post、Put、Delect都是一樣,所以只列出一次在Get.cs 中 Initial HttpClient的程式碼。
public class Get
{ private HttpClient API_CLIENT = null; public Get() { using(ApiSetting _apiSetting = new ApiSetting()) { API_CLIENT = _apiSetting.CreateHttpClient(); } } // … } |
7.
接下來是真正HttpClient從Web APi操控資料的部分~~
GET (取得所有資料)
GET (取得所有資料)
public void GetWebApi()
{ String msg; //使用非同步方法 HttpResponseMessage resp = API_CLIENT.GetAsync(ApiSetting.ROUTE_URI).Result; if (resp.IsSuccessStatusCode) { var books = resp.Content.ReadAsAsync<IEnumerable<Book>>().Result; foreach (var book in books) { msg = String.Format("代號 {0},書名 {1},價格 {2} \n", book.ID, book.NAME, book.PRICE.ToString()); } } else { msg = String.Format("{0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase)); } Console.WriteLine(msg); } |
GET (取得單筆資料)
public void GetWebApi_ById(String id)
{ String msg; //組出GET Uri : api/Book/{id} String getRouteUri = ApiSetting.ROUTE_URI + id; //使用非同步方法 HttpResponseMessage resp = API_CLIENT.GetAsync(getRouteUri).Result; if (resp.IsSuccessStatusCode) { var book = resp.Content.ReadAsAsync<Book>().Result; msg = (book == null) ? "查無資料!" :String.Format("代號 {0},書名 {1},價格 {2} \n", book.ID, book.NAME, book.PRICE.ToString()); } else { msg = String.Format("{0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } Console.WriteLine(msg);
}
|
POST (建立單筆資料)
public void PostWebApi(Book book)
{ String msg = ""; //方法一: 使用 PostAsJsonAsync var resp = API_CLIENT.PostAsJsonAsync(ApiSetting.ROUTE_URI, book).Result; ///方法二: 使用 PostAsync /* // Create the JSON formatter. MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter(); // Use the JSON formatter to create the content of the request body. HttpContent content = new ObjectContent<Book>(book, jsonFormatter); // Send the request. HttpResponseMessage resp = API_CLIENT.PostAsync("api/book", content).Result; */ if (resp.IsSuccessStatusCode){ msg = String.Format("新增成功 : {0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } else{ msg = String.Format("新增失敗 : {0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } Console.WriteLine(msg); } |
DELET (刪除單筆資料)
public void DeleteWebApi(String id)
{ String msg = ""; //組出DELETE Uri : api/Book/{id} String delRouteUrl = ApiSetting.ROUTE_URI + id; ///使用 DeleteAsync var resp = API_CLIENT.DeleteAsync(delRouteUrl).Result; if (resp.IsSuccessStatusCode){ msg = String.Format("刪除成功 : {0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } else{ msg = String.Format("刪除失敗 : {0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } Console.WriteLine(msg); } |
PUT (更新單筆資料)
public void PutWebApi(Book book)
{ String msg = ""; ///組出PUT Uri : api/Book/{id} String putRouteUri = ApiSetting.ROUTE_URI + book.ID; ///使用 PutAsJsonAsync var resp = API_CLIENT.PutAsJsonAsync(putRouteUri, book).Result; if (resp.IsSuccessStatusCode){ msg = String.Format("更新成功 : {0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } else{ msg = String.Format("更新失敗 : {0} {1}", (int?)resp.StatusCode, resp.ReasonPhrase); } Console.WriteLine(msg); } |
9.
Reference:
Calling a Web API From a .NET Client (C#)
Calling a Web API From a .NET Client (C#)
10.
結束
2013年6月6日 星期四
[C#] 使用jQuery取得WebApi服務
使用jQuery取得WebApi服務
延續我們已經建立好的Book Web Api,
除了利用HttpClient ( 文章:使用HttpClient取得WebApi服務 ) 去使用WebApi的CRUD方法。 我們也也可以選擇在前端網頁直接用jQuery使用Web Api。
2.
加入一個MVC4 Web應用程式專案,名稱:Mvc.Thru.WebApi
Page
|
功能
|
對應的CRUD方法
|
Index
|
列出所有書籍,
查詢某一本書籍 |
GET
|
Create
|
建立一本書籍資料
|
POST
|
Edit
|
1.
編輯某本書籍(更新或刪除)
2.
從Index帶URL參數過來。
|
PUT,
DELETE
|
所以我們在BookController中再加入以下程式碼:
public class BooksController : Controller
{ public ActionResult Index() { return View(); } public ActionResult Create() { return View(); } public ActionResult Edit(String id) { return View(); } } |
@{
ViewBag.Title = "Book Index"; } @section scripts { ///新增按鈕事件 function RedirectCreatePage() { location.href = "/Book/Create"; //導向至Create頁面 } <script src="~/Scripts/CallWebApi-Get.js"></script> } <!--功能--> <div> <form> <label for="bookId" >以ID查詢 : </label> <input type="text" id="tb_bookId" maxlength="3" /> <input type="button" id="bt_search" value="Search"/> </form> </div> <!--第二個div放單筆查詢Book的資料--> <div> <p id="book"></p> </div> <!--第三個div放所有查詢Book的資料--> <div> <table id="BookList" > <tr> <td>代號</td><td></td> <td>書籍名稱</td><td></td> <td>價錢</td> </tr> </table> </div>
<!--第四個div放新增按鈕-->
<div> <input type="button" id="bt_create" value="新增" onclick="RedirectCreatePage();"/> </div> |
@{
ViewBag.Title = "Create"; Layout = "~/Views/Shared/_Layout.cshtml"; } @section scripts { <script src="~/Scripts/CallWebApi-Create.js"></script> } <h2>新增資料</h2> <label for="ID">代號</label> <input type="text" id="tb_id" value="" /> <label for="NAME">書籍名稱</label> <input type="text" id="tb_name" value=""/> <label for="PRICE">價錢</label> <input type="text" id="tb_price" value="0"/> <br /> <input type="button" id="bt_create" value="新增"/> |
@{
ViewBag.Title = "Edit"; Layout = "~/Views/Shared/_Layout.cshtml"; } @section scripts
{
<script src="~/Scripts/CallWebApi-Put.js"></script> <script src="~/Scripts/CallWebApi-Delete.js"></script> } <h2>編輯資料</h2> <label for="ID">代號</label> <input type="text" readonly="true" id="tb_id" value="@ViewBag.ID" /> <label for="NAME">書籍名稱</label> <input type="text" id="tb_name" value="@ViewBag.NAME"/> <label for="PRICE">價錢</label> <input type="text" id="tb_price" value="@ViewBag.PRICE"/> <br /> <input type="button" id="bt_update" value="更新"/> <input type="button" id="bt_delete" value="刪除"/> |
因為Edit頁面上的資料會從Index帶URL參數過來,所以我們放了幾個ViewBag在上面,將顯示ID的TextBox設成唯獨,並在Controller中稍加一些程式碼:
public ActionResult Edit(String id)
{ //設定帶過來的值到頁面上 ViewBag.ID = id; ViewBag.NAME = Request["NAME"].ToString(); ViewBag.PRICE = Request["PRICE"].ToString(); return View(); } |
6. 以上HTML和後端都準備好之後,目前頁面可正常瀏覽,但是沒辦法操作資料,我們接下來便要開始撰寫jQuery 來使用Web Api。 如果剛才還沒有新增前面四支空的 js檔,請如下新增在Script資料夾。


7.
jQuery 使用Web Api GET方法:CallWebApi-Create.js (載入於Index.cshtml)
$(function () {
//Web api url var API_URL = "http://localhost:33855/api/Book/"; //利用Get方式取得。 $.getJSON( API_URL, function (data) { $.each(data, function (key, val) { //格式化文字資料,以方便顯示 // var str = val.NAME + ' : $' + val.PRICE; //將Book資料設定成 li 項目,再加入 ul 元素中 //$('<li/>', { html: str }).appendTo($('#books')); var content = ""; content +="<tr>"; content += "<td>" + val.ID + "<td/>"; content += "<td>" + val.NAME + "<td/>"; content +="<td>"+val.PRICE+"<td/>"; content += "<tr/>"; $('#BookList').append(content); }); }).fail( function (jqXHR, textStatus, err) { alert("Error : " + err.toString()); }); $('#bt_search').bind("click", function () { var id = $('#tb_bookId').val(); $.getJSON( API_URL + id, function (data) { var str = data.NAME + ' : $' + data.PRICE; var linkStr = "<a href='/Book/Edit/" + data.ID + "?NAME=" + data.NAME + "&PRICE="+data.PRICE+"'>" + str + "</a>"; $('#book').append(linkStr); //$('#book').html(str); }).fail( function (jqXHR, textStatus, err) { $('#book').html('Error : ' + err); }); }); }); |
※
第一段是使用$.getJSON 方法去使用Web APi的GET,取得資料後,再把每一筆資料放入Index View 裡面的<Table>中。
※
第二段是實作查詢單筆的Click事件,依舊是使用Web APi的GET,只不過我們在api Url最後加上單筆書籍的ID,讓Web Api回傳單筆資料。 再將此筆資料以超連結<a
href=..></a>的格式放入頁面, 讓使用者點選此筆連結後,可直接到Edit頁面。
8. jQuery 使用Web Api PUT方法:CallWebApi-Put.js (載入於Edit.cshtml)
還記得我們在Edit頁面的資料是從Index帶過來的,所以上面的步驟完成後,我們目前可以看到Edit頁面上的資料已經自動帶入了,我們只要再實作【更新】的Click事件裡面使用Web Api的PUT方法。


$(function () {
//Web api url var API_URL = "http://localhost:33855/api/Book/"; $('#bt_update').bind("click", function () { //取得Book的ID var id = $('#tb_id').val(); //要給WebApi的JSON字串 var uptJson = JSON.stringify( { ID: id, NAME: $('#tb_name').val(), PRICE: parseInt($('#tb_price').val()) }); //以ajax呼叫WebApi的PUT方法 $.ajax({ url: API_URL + id, cache:false, type: "PUT", contentType: "application/json; charset=utf-8", data: uptJson, success: function () { location.href = "/Book/"; } }).fail( function(jqXHR, textStatus, err){ alert("更新失敗:"+err); }); }); }); |
※
這邊我們必須指定要使用的Http方法,以及送過去的ContentType、data(JSON)。
※
更新成功後,會直接回到Index頁面。
9.
jQuery 使用Web Api DELETE方法:CallWebApi-Delete.js (載入於Edit.cshtml)
Edit頁面上,還有一個刪除功能,我們一併完成它 …
Edit頁面上,還有一個刪除功能,我們一併完成它 …
$(function () {
//Web api url var API_URL = "http://localhost:33855/api/Book/"; $('#bt_delete').bind("click", function () { //取得Book的ID var id = $('#tb_id').val(); //以ajax呼叫WebApi的Delete方法 $.ajax({ url: API_URL + id, cache: false, type: "DELETE", success: function () { location.href = "/Book/"; } }).fail( function (jqXHR, textStatus, err) { alert("刪除失敗:" + err); }) }); }); |
※
因為Delete方法只要知道ID,所以就省略了設定data的部分。
10.
jQuery 使用Web Api POST方法:CallWebApi-Post.js (載入於Create.cshtml)
$(function () {
//Web api url var API_URL = "http://localhost:33855/api/Book/"; $('#bt_create').bind("click", function () { //取得Book的ID var id = $('#tb_id').val(); //要給WebApi的JSON字串 var uptJson = JSON.stringify( { ID: id, NAME: $('#tb_name').val(), PRICE: parseInt($('#tb_price').val()) }); //以ajax呼叫WebApi的PUT方法 $.ajax({ url: API_URL, cache:false, type: "POST", contentType: "application/json; charset=utf-8", data: uptJson, success: function () { location.href = "/Book/"; } }).fail( function(jqXHR, textStatus, err){ alert("新增失敗:"+err); }); }); }); |
13.
結束