C# WebAPI學習

WebApi是微軟在VS2012 MVC4版本中綁定發行的,WebApi是徹底基於Restful標準的框架。RestFul: (英文:Representational State Transfer,簡稱REST)網上關於Restful定義的資料不少,我我的理解的Restful api 是指基於資源的定義的接口,它的全部接口都是對資源的操做。REST的核心原則是將你的API拆分爲邏輯上的資源。這些資源經過http被操做(GET ,POST,PUT,DELETE).Restful Api接口標準的定義知足CURD,標準的接口定義以下:html

  • Post:新增記錄
  • Put:修改記錄
  • Get:獲取數據
  • Delete:刪除數據

webapi標準的定義形式爲:每一個controller都對應一個Model,controller中的接口都應該是對controller所對應的那個model進行的操做,因此上訴的post,get,put,delete都是對model所對應的資源操做。可是在實際的操做中,可能沒有辦法徹底知足這種定義的形式,力求儘可能知足。web

 

WebAPI項目和典型的MVC項目同樣,包含主要的Models,Views,Controllers等文件夾和Global.asax文件。Views對於WebAPI來講沒有太大的用途,Models中的Model主要用於保存Service和Client交互的對象,這些對象默認狀況下會被轉換爲Json格式的數據進行傳輸,Controllers中的Controller用於提供服務。和普通的MVC同樣,Global.asax用於配置路由規則。json

在實際應用中,Controller是WebAPI的連接服務器和客戶端的窗口。Controller的好壞影響整個系統的設計。Controller中是各類Action接口,對於Action接口,咱們有必要對其接收的參數和返回值瞭解。api

Action返回類型

WebAPI服務函數的返回值主要能夠分爲void、普通對象、HttpResponseMessag、IHttpActionResult 四種,這裏簡單的介紹一下。服務器

Void類型

通常來講,Delete和Put類型的求情返回void類型的值,如:架構

複製代碼
public class DepartmentController : ApiController
{
        public void Delete(int id)
        {
            
        }
}
複製代碼

不過一個交互性好的接口,應該返回正確的Http status code,如返回200,對列子作修改:app

複製代碼
public class DepartmentController : ApiController
{
    public HttpStatusCode Delete(int id)
  {
    return HttpStatusCode.OK;
  }
}    
複製代碼

 

普通對象

普通對象一般是由Get接口返回。例如:框架

複製代碼
public class CompanyController : ApiController
{
  public Company Get(int id)
   {
     return CompanyInfo;
   }
}
複製代碼

HttpResponseMessag

HttpResponseMessage是標準Http應答了,此時服務器並不作任何處理,能夠直接將HttpResponseMessage發送給客戶端。asp.net

複製代碼
  public HttpResponseMessage Get()
  {
         var response = Request.CreateResponse(HttpStatusCode.OK);
         response.Content = new StringContent("Success", Encoding.UTF8);
             
         return response;
   }
複製代碼

IHttpActionResult

IHttpActionResult是Web API 2中引入的一個接口,IHttpActionResult是HttpResponseMessage的一個工廠類。IHttpActionResult是WebAPI中推薦的標準返回值,ApiController類中也提供了很多標準的工廠函數方便咱們快速構建它們,如BadRequest,Conflict,Ok,NotFound等,一個簡單的示例以下:函數

複製代碼
 public IHttpActionResult Get(int id)
 {
      var dto = new ProductDataDTO();
      dto = AutoMapper.Mapper.Map<ProductDataDTO>(ProductDataService.QueryProductData (id));
      return Ok(dto);
}
複製代碼

 

Action參數類型

Get請求的參數,均在URI中給出,比較簡單,不作過多說明。下面主要對POST請求的參數作一下說明。

POST請求

單一POST參數

單一的參數請求,須要使用[FromBody]標記參數,以下圖所示:

[AcceptVerbs("POST")]
public string Post([FromBody]string data)
{
     return string.Format(@"Data:{1}",  data);
}

除了使用[FromBody]標記參數外,也可使用dynamic關鍵字標記參數。

多個參數的POST請求

有了上面的經驗,多個參數的例子,按照常理來講,應該以下所示

[AcceptVerbs("POST")]
 public string Post([FromBody]string data, [FromBody]string name)
 {
     return string.Format(@"Name:{0},Data:{1}", name, data);
 }

但在實際調用中卻報錯,報錯以下:

查了資料,緣由是在一個接口中,被[FromBody]修飾的參數只能有一個。對此,咱們能夠將上面的兩個參數封裝爲一個對象傳遞。以下:

複製代碼
public class Person
{
  public string name { set; get; }
  public string message { set; get; }
}

......


[AcceptVerbs("POST")]
public string TEST4([FromBody]Person data)
{
  return string.Format(@"Name:{0},Message:{1}", data.name, data.message);
}
複製代碼

除此以外,還有另一種方式實現,使用[FromURi]關鍵字,以下所示:

public string TEST2([FromUri]string data,[FromBody]string name)
{
  return string.Format(@"Name:{0},Data:{1}",name,data);
}

須要說明的是,在WebApi的接口參數中,在沒有標記的狀況下,參數默認是[FromUri]形式,Get請求的接口的參數都是FromUri,顧名思議是從Uri獲取數據。一個接口能夠有多個FromUri參數(這些參數通常都是簡單參數),可是隻能有一個FromBody的參數。

就剛纔的例子而言,data數據在Uri中獲取,而name數據則從body中獲取。

傳遞對象

有了上面的例子,其實傳遞對象在上面已經講過了,就是使用[FromBody]或dynamic標記參數。

傳遞不一樣的多個對象

這種狀況,最近打算寫這篇文章的時候,查找資料的時候,在其餘人的博文中看到的,地址以下:http://www.cnblogs.com/babycool/p/3922738.html,裏面提到了傳遞多個不一樣對象的狀況,我的也嘗試去試着調試,可是一直沒有成功,也就很差作過多的說明。後來想了下,其實能夠另闢蹊徑解決這個方法,新建一個對象,將要傳遞的對象作了屬性,這樣來傳遞給後臺接口。關於最後這種方式,你們感興趣能夠去看看原文。

百聞不如一見,百見不如一作,只有作了,才知道問題出如今哪兒,才能去解決問題。
 
 
 

數據序列化


Web API 框架目前支持兩種數據格式的序列化:Json 及 Xml。在不作任何配置的狀況下,若是 Http 請求中,HttpHeader 中 Accept 被指定爲 accept: application/xml,則 Web API 會自動把數據使用 xml 進行序列化,不然使用 json 序列化。 
若是指望不使用 xml 序列化數據,咱們能夠經過 GlobalConfiguration.Configuration.Formatters 來進行配置:config.Formatters.Remove(config.Formatters.XmlFormatter)。

通常狀況下,咱們會使用 Json 序列化。跟 ASP.NET MVC 的 Json 序列化不一樣的是,Web API 使用了 Newtonsoft.Json 框架來進行序列化。(例如,JsonMediaTypeFormatter.SerializerSettings 屬性就是 Newtonsoft.Json.JsonSerializerSettings 類型,能夠直接對序列化進行配置。) 
Json 序列化支持對匿名類型進行進行序列化,這大大方便了開發人員,例如,咱們能夠隨意組裝數據並直接返回:

   1:  [HttpGet]
   2:  public IEnumerable AllGet()
   3:  {
   4:      return new string[] { "Item1", "Item2" }.Select(s => new
   5:      {
   6:          Name = s,
   7:          Code = s,
   8:          Items = new ArrayList
   9:          {
  10:              new { Name = "Item1" },
  11:              new { Name = "Item2" },
  12:              new { Name = "Item3" },
  13:              new { Name = "Item4" },
  14:          }
  15:      });
  16:  }

另外,Web API 提供了 HttpResponseMessage 類型可做爲返回值,使得開發人員能夠對 HttpResponse 作一些更詳細的設置。並且,若是不指望修改返回值類型而直接返回 HttpResponse 時,可使用 HttpResponseException 間接返回一個 HttpResponseMessage。

 

Action 匹配


Web API 框架默認是基於 Restful 架構模式的,與 ASP.NET MVC 有區別的是,它會根據 Http 請求的 HttpMethod(Get、Post、Put、Delete) 來在 Controller 中查找 Action,規則是:Action 名中是否以 Get、Post 開頭?Action 上標記 HttpGet、HttpPost 等標記?並會徹底忽視 Action 的方法名。

例如,Web API 對於資源的 CRUD 操做,採用以下格式: 
get /API/models/ 查詢全部實體 
get /API/models/1000 查詢id爲1000的實體 
post /API/models/ {id:-1, name:'name'} 添加一個實體 
put /API/models/ {id:1000, name:'name'} 更新指定實體 
delete /API/models/1 刪除指定實體

因爲忽視了方法名,因此的幾個方法,在調用時會拋出異常: 
image

image

 

在面向服務的架構中,每每不會直接把底層的實體公佈出來,讓客戶端直接進行 CRU 操做;而是公佈一些粗粒度的 RPC 形式的服務操做。要使用 Web API 框架,咱們須要修改默認的配置。例如,讓客戶端在調用時顯式指定 action 名稱:

   1:  config.Routes.MapHttpRoute(
   2:      name: "DefaultApi",
   3:      routeTemplate: "api/{controller}/{action}/{id}",
   4:      defaults: new { id = RouteParameter.Optional }
   5:  );

這樣,因爲顯式指定了 Action 名稱,Web API 會使用該名稱來查找對應的 Action 方法,而再也不按照 HttpMethod 約定來查找對應的 Action。例如,對於如下 API 的調用以下:

   1:  [HttpGet]
   2:  public HttpResponseMessage Login(string userName, string password)
   3:  {
   4:      return Request.CreateResponse(HttpStatusCode.NotFound);
   5:  }

調用方法: 
get /api/account/login/?username=hqf@qq.com&password=dsd

 

關於 POST 參數綁定


Web API 相對於 ASP.NET MVC,使用了新的參數綁定類。要注意的是,Action 參數列表中只能有一個參數能夠從 Http Post Body 中反序列化出來。若是參數列表中只有一個參數,並且它的類型是一個複雜類型,那麼 Web API 會直接把 Body 嘗試反序列化爲該類的對象。若是有多個參數,那麼要從 Body 反序列化的那個參數,須要標記上 [FromBodyAttribute]。 
相關內容,比較複雜,能夠參考如下文章: 
http://www.cnblogs.com/sicket/archive/2012/06/28/2567129.html
http://www.cnblogs.com/lushuicongsheng/archive/2012/10/27/2742214.html
http://www.tuicool.com/articles/eQzyEv 
http://weblogs.asp.net/cibrax/archive/2012/08/10/binding-form-data-in-asp-net-web-api.aspx

 

不錯的示例代碼


MSDN 上有一個比較全面的示例代碼: 
http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7

相關文章
相關標籤/搜索