1. 程式人生 > WINDOWS開發 >使用ASP.Net WebAPI構建REST服務

使用ASP.Net WebAPI構建REST服務

一、建立WebAPI應用程式

1、Web API 1版本

首先建立一個Asp.Net MVC 4 Web應用程式(我這裡用的是Visual Studio 2012)。

技術分享圖片

在出來的模板中選擇Web API。點選確定後,就建立了一個空的WebAPI服務。

技術分享圖片

2、 Web API 2版本

技術分享圖片

點選確定後,就建立了一個空的WebAPI服務。此時只有一個空專案,還沒有任何功能

在進行下一步之前,首先我們來看一下REST的基本操作模型,大致可以分為如下四種:

  • POST — 建立資源
  • GET — 檢索資源
  • PUT — 更新資源
  • DELETE — 刪除資源

非常經典的CRUD模型。

在Web API中實現這樣一個的模型是非常簡單的,直接使用嚮導建一個Controller即可

技術分享圖片

技術分享圖片

在Web API中生成預設的ValuesController

技術分享圖片

預設的模板內容如下:

public class ValuesController : ApiController
{
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1",value2" };
        }

         GET api/values/5
        string Get(int id)
        {
            
return value; } POST api/values void Post([FromBody]string value) { } PUT api/values/5 void Put(int id,[FromBody] DELETE api/values/5 void Delete( id) { } }

這其實已經幫我們實現了一個最基本的服務了,不過這個服務中只實現了Get,它支援如下兩種中方式的URL訪問(其它的方式也能訪問,但沒有具體的效果):

  • api/values 訪問所有的Value列表

  • api/values/{id} 根據ID訪問Value

按Ctrl + F5中執行,在瀏覽器中輸入相應的地址即可看到結果

技術分享圖片

下面我們要做的就是完善它,實現一個簡單的查詢功能,這裡我引用了微軟官方的一個例子: ProductsController : ApiController { Product[] products = new Product[] { new Product { Id = 1,Name = Tomato SoupGroceries1 },2,0);">Yo-yoToys3.75M3,0);">HammerHardware16.99M } }; public IEnumerable<Product>return products; } public IHttpActionResult Get(var product = products.FirstOrDefault((p) => p.Id == id); if (product == null) { NotFound(); } Ok(product); } } Product { int Id { get; set; } string Name { string Category { decimal Price { ; } }

此時,我們就可以在瀏覽器中看到結果了(由於Controller改名字了,此時的地址就變成了api/products)

技術分享圖片

到此為止,一個基於Asp.net Web API的 簡單的REST Web服務就構建完成了,由於篇幅所限,這裡就不做更多的介紹了,跟多資訊可以參看微軟官方文件:Getting Started with ASP.NET Web API 2

備註:WebAPI升級到 WebAPI 2如下命令更新web Api:

Install-Package Microsoft.AspNet.WebApi

二、路由

REST並沒有像傳統的RPC服務那樣顯式指定了伺服器函式的訪問路徑,而是將URL根據一定的規則對映為服務函式入口,這個規則就稱之為路由。Asp.Net WebAPI的路由方式和Asp.Net MVC是相同的,它支援兩種路由方式,傳統的路由對映和特性路由。 路由規則WebApiConfig.cs中定義。

技術分享圖片

它的預設內容如下:static WebApiConfig { void Register(HttpConfiguration config) { Web API configuration and services Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: DefaultApi,routeTemplate: api/{controller}/{id}new { id = RouteParameter.Optional } ); } }

它預設註冊了兩種路由規則,第一行註冊的是特性路由,第二行註冊的則是傳統的對映路由。預設情況下,由於我們沒有編寫特性路由規則,則是按照傳統的Controller方式對映路由。

關於路由規則,MSDN文件ASP.NET 路由介紹得非常詳細,但由於其介紹得太詳細了,反而不容易得其門而入,這裡我只拿預設的路由規則來簡單但的介紹一下我的理解,它的uri格式是這樣的"api/{controller}/{id}",其中id是可選的。拿前文的例子來說吧,

  1. 當我們對api/products地址進行訪問的時候,系統則會首先找到名為ProductsController的控制器。
  2. 然後,根據訪問方式查詢函式,由於這裡是Get操作,則查詢Get開頭的函式, 這裡會找到Get()和Get(int id)兩個過載版本。
  3. 最後,根據引數來匹配具體的函式,因為這裡沒有帶引數id。因此匹配到了Get()函式,返回了所有的集合。

另外,這裡也有幾個常用的衍生規則:

  1. 根據操作方式找函式的時候,只需要匹配首部即可,因此我們編寫函式的時候寫成Get()和GetProduct()都是可以的。,
  2. 根據操作方式找函式的時候查詢的時候不分大小寫,因此寫成Get()或get()都是可以的

當我們使用帶引數的版本時候,也有幾個需要注意的地方:

  1. 引數名不分大小寫,我們寫成id或ID都是可以的
  2. 引數名要求嚴格匹配的,我們寫成ID2是不行的,此時則會匹配到錯誤的結果Get()

預設的規則雖然大多數的時候還是比較方便的,但是很多時候我們需要手動指定個性化的路由規則。例如,我們可以自定義一個按名稱來查詢的url:api/products/name=xxx。這個時候則可以用特性路由快速的實現了:

[Route(api/{controller}/name={name})]
public IHttpActionResult GetByName(string name)

關於特性路由,MSDN原文Attribute Routing in ASP.NET MVC 5介紹得非常詳細,國內也有非常不錯的譯文版本Attribute Routing in ASP.NET MVC 5 翻譯及補充,這裡就不做多少介紹了。

三、返回值

Asp.Net WebAPI服務函式的返回值主要可以分為void、普通物件、HttpResponseMessag、IHttpActionResult e四種,本文這裡簡單的介紹一下它們的區別。

1、返回void

返回void一般常用於Put和Delete函式。 id) { }

當服務函式執行完成後,伺服器端並不是啥都不幹直接把客戶端給斷掉,而是傳送一個標準的204 (No Content)的Http應答給客戶端。

HTTP/1.1 204 No Content
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?Zjpc5paH5qGjXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVx2YWx1ZXNcMQ==?=
X-Powered-By: ASP.NET
Date: Fri,02 May 2014 13:32:07 GMT

2、返回普通物件

返回普通物件時,伺服器將返回的物件序列化後(預設是json),通過Http應答返回給客戶端。例如, ValuesController : ApiController { hello; } }

此時的返回結果是:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?Zjpc5paH5qGjXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVx2YWx1ZXM=?=
X-Powered-By: ASP.NET
Date: Fri,02 May 2014 12:54:18 GMT
Content-Length: 7
"hello"

非同步返回普通物件:

WebAPI也是支援非同步返回物件的:async Task< Get() { await Task.Delay(100); ; }

非同步返回的時候,伺服器非同步等待函式執行完成後再將返回值返回給物件。由於這個過程對於客戶端來說是透明的,這裡就不列舉報文了。

3、返回HttpResponseMessage

HttpResponseMessage是標準Http應答了,此時伺服器並不做任何處理,直接將HttpResponseMessage傳送給客戶端。public HttpResponseMessage Get() { var response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent( response; }

此時的返回結果如下:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 5
Content-Type: text/plain; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?Zjpc5paH5qGjXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVx2YWx1ZXM=?=
X-Powered-By: ASP.NET
Date: Fri,02 May 2014 13:09:57 GMT
hello

可以看到,這裡返回的content-type仍然是原始定義的text型別,而不是json。要實現想上面的例子所示的結果,則需要將Get函式改寫為如下形式return Request.CreateResponse(HttpStatusCode.OK,0);">); }

4、返回IHttpActionResult

IHttpActionResult是Web API 2中引入的一個介面,它的定義如下:interface IHttpActionResult { Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken); }

從它的定義可以看出,IHttpActionResult是HttpResponseMessage的一個工廠類,最終還是用於構建HttpResponseMessage返回,由於它可以取消,因而可以實現更為強大的返回功能(如流傳輸)。當服務函式返回IHttpActionResult物件時,伺服器執行該物件的ExecuteAsync函式,並非同步等待至函式完成後,獲取其返回值HttpResponseMessage輸出給客戶端。

IHttpActionResult是WebAPI中推薦的標準返回值,ApiController類中也提供了不少標準的工廠函式方便我們快速構建它們,如BadRequest,Conflict,Ok,NotFound等,一個簡單的示例如下: id) { id); ) { NotFound(); } Ok(product); }