初試ASP.NET Web API/MVC API(附Demo)

寫在前面

  ASP.NET Web API是​​一個框架,能夠很容易構建達成了普遍的HTTP服務客戶端,包括瀏覽器和移動設備。是構建RESTful應用程序的理想平臺的.NET框架。html

  上面是微軟對Web API給出的定義,其中包含兩個關鍵字:HTTP和RESTful,其實從這一方面,你們就能夠看出Web API和它的同胞兄弟:WebService和WCF有些不一樣了。node

HTTP

  對於HTTP你們都不是很陌生,由於咱們天天瀏覽網頁填寫的URL就是HTTP開頭,但只是知道有這個東西,確沒有想過它是什麼,就好像咱們對世間萬物有着模糊的認識,但認識東西的確不多。web

  也能夠從另外一方面去理解,曾經看一個電視節目,有個嘉賓在錄製的過程當中,忽然擡起頭對着天花板仰望,而後主持人很驚訝問他在幹嘛?他說:我在思考宇宙有沒有盡頭?主持人接着問:那宇宙有沒有盡頭?他淡然的回答道:有就有,沒有就沒有。固然觀衆和主持人都笑做一團,你會笑嗎?透過現象看本質,其實這個思想和老莊的思想很合拍,扯遠了。編程

HTTP即超文本傳送協議。json

超文本傳輸協議 (HTTP-Hypertext transfer protocol) 是一種詳細規定了瀏覽器和萬維網服務器之間互相通訊的規則,經過因特網傳送萬維網文檔的數據傳送協議。api

  從定義中看出HTTP是一種協議,超文本傳輸協議,那什麼是超文本?和咱們所說的富文本有些區別,超文本也是一種文本格式,那能夠把它當作是文本與文本之間關聯而組成的網狀文本,有點相似於面向對象中對象的集合,雖然是對象的集合,但自己也是一個對象。跨域

  HTTP協議有下面三個基本特色:瀏覽器

  • 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。請求方法經常使用的有GET、HEAD、POST。每種方法規定了客戶與服務器聯繫的類型不一樣。因爲HTTP協議簡單,使得HTTP服務器的程序規模小,於是通訊速度很快。
  • 靈活:HTTP容許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記。
  • 無狀態:無狀態是指協議對於事務處理沒有記憶能力。缺乏狀態意味着若是後續處理須要前面的信息,則它必須重傳,這樣可能致使每次鏈接傳送的數據量增大。

  相對於Web API來講,HTTP不僅是爲了生成Web頁面,它也是一個強大的平臺建設公開服務和數據的API。HTTP是簡單、 靈活和無處不在,所以幾乎任何平臺均可以有一個HTTP庫,所以,HTTP服務能夠到達範圍普遍的客戶端,包括瀏覽器、移動設備和傳統的桌面應用程序。服務器

RESTful

  RESTful架構概念是Fielding提出的,Fielding這號人物就是上面HTTP協議的主要設計者之一。咱們先看下RESTful這個詞,ful是跟在名詞以後,表示程度,什麼什麼的,例如helpful樂於助人的,所以咱們能夠看出符合REST的架構就能夠稱爲RESTful,接着咱們看下REST,全稱爲「Representational State Transfer」,意爲「表現層狀態轉化」網絡

在符合架構原理的前提下,理解和評估以網絡爲基礎的應用軟件的架構設計,獲得一個功能強、性能好、適宜通訊的架構。  -Fielding

  這是Fielding在論文中所提到的,對於REST雖然說是架構,但若是深刻一點,就像是HTTP協議同樣,能夠當作一種規則或是協議。咱們從一個地點到另外一個地點,能夠坐汽車、高鐵、飛機等,對於REST就像是其中的一種交通方式,但REST的根本是HTTP協議,也就是說REST是基於HTTP協議的,這點就像坐汽車必需要有公路,坐高鐵必需要有鐵路是同樣的道理,有時候爲何選用REST,就像咱們從南京到徐州,選擇坐高鐵而不選擇坐飛機同樣。

  上面這個比喻可能不太恰當,可是思想都是相同的,若是有可能的話能夠看下一些哲學方面的書,像莊子的道德經,畢竟編程是哲學或是藝術的另外一類體現,又扯遠了。

  「Representational State Transfer」咱們分解下:

  • Representational 表現層:表現層表現什麼,應該呈現資源(Resources),一個圖片、一段文字、一個文件都成爲資源,每一個資源都用一個URI(統一資源定位符)指向它,表現層就是調用URI把資源呈現出來,並且只是呈現,不作其餘操做。舉個例子:有些網址最後的".html"後綴名是沒必要要的,由於這個後綴名錶示格式,屬於"表現層"範疇,而URI應該只表明"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段纔是對"表現層"的描述。
  • State Transfer 狀態轉化:訪問一個網站,就表示客戶端和服務器發生一次交互行爲,在這個過程當中,就不發生數據和狀態的轉化,上面說到HTTP協議具備無狀態性,若是客戶端操做服務器,必需要狀態轉化,這個體如今表現層上,因此叫「表現層狀態轉化」

  經過上面的理解,能夠總結下什麼是RESTful架構:

  1. 每個URI表明一種資源。
  2. 客戶端和服務器之間,傳遞這種資源的某種表現層。
  3. 客戶端經過四個HTTP動詞(PUT、GET、POST和DELETE),對服務器端資源進行操做,實現"表現層狀態轉化"。

建立Web API

  關於Web API的實現方式,.net提供了一套機制就是ASP.NET MVC API,相似MVC的方式,實現起來很簡單,也不須要你去關注HTTP和RESTful的一些東西,當你去新建項目的時候,一切東西.net都幫你搞定了,是好仍是很差?只能呵呵笑過。

  下面咱們就一步一步的建立一個ASP.NET MVC API

  1,新建ASP.NET MVC WebMvcApiDemo程序,選擇Web API模板類型。

  2,建立News模型,雖然建立的是MVC項目,可是咱們通常只用到控制器和模型。

 1     public class News
 2     {
 3         /// <summary>
 4         /// 新聞ID
 5         /// </summary>
 6         public int Id { get; set; }
 7         /// <summary>
 8         /// 新聞標題
 9         /// </summary>
10         public string Title { get; set; }
11         /// <summary>
12         /// 新聞內容
13         /// </summary>
14         public string Content { get; set; }
15         /// <summary>
16         /// 新聞做者
17         /// </summary>
18         public string Author { get; set; }
19         /// <summary>
20         /// 發佈新聞時間
21         /// </summary>
22         public DateTime CreateTime { get; set; }
23     }

  3,建立數據模擬類NewsRepository,用於查詢數據。

 1     public class NewsRepository
 2     {
 3         public IEnumerable<News> GetAllNews()
 4         {
 5             News[] news = new News[] 
 6             { 
 7                 new News { Id = 1, Title="新聞標題1", Content="新聞內容1", Author="xishuai", CreateTime=DateTime.Now }, 
 8                 new News { Id = 2, Title="新聞標題2", Content="新聞內容2", Author="xishuai", CreateTime=DateTime.Now }, 
 9                 new News { Id = 3, Title="新聞標題2", Content="新聞內容3", Author="xishuai", CreateTime=DateTime.Now }
10             };
11             return news;
12         }
13     }

  4,建立NewsController控制器,注意的是:新建控制器的時候,模板選擇「空 API 控制器」,與MVC控制器不一樣的是,API控制器繼承ApiController基類。在咱們新建ApiDemo的MVC項目的時候,自動生成了一個ValuesController API控制器,打開後咱們發現,有不少自動生成的方法,請求方式就是咱們上面說GET、POST、PUT和DELETE的四種HTTP請求方式,咱們這邊作一個Get的,獲取所有新聞或是指定新聞ID獲取,返回結果格式爲XML。

 1     public class NewsController : ApiController
 2     {
 3         /// <summary>
 4         /// GET獲取所有新聞
 5         /// </summary>
 6         /// <returns></returns>
 7         [HttpGet]
 8         public HttpResponseMessage GetAllNews()
 9         {
10             var news = new NewsRepository().GetAllNews();
11             return new HttpResponseMessage()
12             {
13                 RequestMessage = Request,
14                 Content = new XmlContent(SimpleXmlConverter.ToXmlDocument<News>(news, "NewsRoot"))
15             };
16         }
17 
18         /// <summary>
19         /// GET獲取指定ID新聞
20         /// </summary>
21         /// <param name="ID"></param>
22         /// <returns></returns>
23         [HttpGet]
24         public HttpResponseMessage GetNewsByID(int ID)
25         {
26             var news = new NewsRepository().GetAllNews().Where((p) => p.Id == ID);
27             return new HttpResponseMessage()
28             {
29                 RequestMessage = Request,
30                 Content = new XmlContent(SimpleXmlConverter.ToXmlDocument<News>(news, "NewsRoot"))
31             };
32         }
33     }

  這裏面主要用到兩個轉化類:XmlContent和SimpleXmlConverter,有關這兩個類的詳細代碼能夠下載Demo看下。

  5,路由配置Web API和MVC的路由配置很類似,主要區別是Web API使用HTTP方法而不是URI路徑來選擇動做,路由文件WebApiConfig,以下:

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

  其實寫到這裏建立Web API的代碼就差很少了,固然複雜的操做能夠擴充,用.net開發就是這麼簡單,只要完成業務邏輯就好了,呵呵。

調用Web API

  調用Web API有不少種方式,js能夠調用,就像咱們寫MVC請求數據同樣,這種是同一域下調用,Web API也是這種方式就沒什麼意思了,若是使用js調用就必須跨域操做,這邊咱們使用HttpClient的方式。

  1,新建控制檯應用程序-ClientDemo。

  2,安裝Web API 客戶端庫,工具-程序包管理器-程序包管理控制平臺,輸入命令:Install-Package Microsoft.AspNet.WebApi.Client

  上面新建的ClientDemo項目.net framework版本是4.0,安裝HttpClient的時候報下面錯誤:

  .net framework版本改成4.5就安裝成功了,難道HttpClient只支持4.5以上?查了下MSDN,HttpClient確實只支持.net framework4.5,難道之前程序若是使用HttpClient要把.net framework改爲4.5?有點鬱悶。

  4,建立HttpClient,先貼下代碼:

 1         static void Main(string[] args)
 2         {
 3             RunAsync().Wait();
 4         }
 5 
 6         static async Task RunAsync()
 7         {
 8             using (var client = new HttpClient())
 9             {
10                 client.BaseAddress = new Uri("http://localhost:8077/");
11                 client.DefaultRequestHeaders.Accept.Clear();
12                 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
13 
14                 string xmlString = await client.GetStringAsync("api/News/GetAllNews");
15                 XmlDocument xmlDoc = new XmlDocument();
16                 xmlDoc.LoadXml(xmlString);
17                 XmlNodeList nodeList = xmlDoc.GetElementsByTagName("News");
18                 foreach (XmlNode node in nodeList)
19                 {
20                     Console.WriteLine("新聞ID:" + node.SelectSingleNode("Id").InnerText);
21                     Console.WriteLine("新聞標題:" + node.SelectSingleNode("Title").InnerText);
22                     Console.WriteLine("新聞內容:" + node.SelectSingleNode("Content").InnerText);
23                     Console.WriteLine("做者:" + node.SelectSingleNode("Author").InnerText);
24                     Console.WriteLine("新聞發佈時間:" + node.SelectSingleNode("CreateTime").InnerText);
25                     Console.WriteLine("======================");
26                 }
27                 Console.ReadKey();
28             }
29         }

  Main 函數調用一個名爲RunAsync的異步方法,而後會阻止,直到RunAsync完成。許多的HttpClient方法是異步,由於他們執行網絡 i/o 操做。MediaTypeWithQualityHeaderValue是定義傳輸格式,若是使用json則爲「application/json」,這邊要與Web API格式一致,XML獲取使用的是GetStringAsync方法,而後轉換爲XmlDocument,網上找了一種GetStreamAsync方法獲取,經過Stream轉化爲字符串,可是轉化後的字符串爲空。

  上面調用Web API的是獲取所有新聞,若是調用經過新聞ID獲取新聞,GetStringAsync的方法參數只須要改成「api/News/GetNewsByID/新聞ID」就能夠了。

  5,關於Web API的發佈問題,這個問題花了很多時間,一個一個問題出現及解決,首先咱們先不急着調用,先發布瀏覽,若是瀏覽器瀏覽沒問題的話再調用。Web API的發佈和MVC差很少,須要注意下面幾點:

  • 文件權限別忘了配置,要配置every one。
  • 應用程序池選擇「ASP.NET v4.0 DefaultAppPool」。
  • 選擇應用程序池以後要配置「ISAPI 和 CGI 限制」的4.0版本設置爲容許,要否則出現「因爲 Web 服務器上的「ISAPI 和 CGI 限制」列表設置,沒法提供您請求的頁面。」的錯誤。
  • 「Newtonsoft.Json」文件引用。
  • 「An error has occurred.Multiple actions were found that match the request」,這個錯誤信息是Web API的路由沒有配置好,要檢查下。
  • 「Response status code does not indicate success: 404 (Not Found)」,這個錯誤信息也是路由問題。
  • 「Response status code does not indicate success: 500 (Internal Server Error).」,這個是服務器問題,也就是Web API的代碼問題。

運行截圖及Demo下載

  Web API瀏覽器請求截圖:

  Web API發佈運行截圖:

  客戶端調用運行截圖:

  Demo下載地址:http://pan.baidu.com/s/1gdopRub

  HTTP請求的四種方法(PUT、GET、POST和DELETE)本篇只是講到GET,HTTP的數據傳輸格式(json、xml等)也只是說了XML,但都是大同小異,觸類旁通可得。

  若是你以爲本篇文章對你有所幫助,請點擊右下部「推薦」,^_^

相關文章
相關標籤/搜索