寫(xiě)在前面ASP.NET Web API是??一個(gè)框架,可以很容易構(gòu)建達(dá)成了廣泛的HTTP服務(wù)客戶端,包括瀏覽器和移動(dòng)設(shè)備。是構(gòu)建RESTful應(yīng)用程序的理想平臺(tái)的.NET框架。 上面是微軟對(duì)Web API給出的定義,其中包含兩個(gè)關(guān)鍵字:HTTP和RESTful,其實(shí)從這一方面,大家就可以看出Web API和它的同胞兄弟:WebService和WCF有些不同了。 HTTP
對(duì)于HTTP大家都不是很陌生,因?yàn)槲覀兠刻鞛g覽網(wǎng)頁(yè)填寫(xiě)的URL就是HTTP開(kāi)頭,但只是知道有這個(gè)東西,確沒(méi)有想過(guò)它是什么,就好像我們對(duì)世間萬(wàn)物有著模糊的認(rèn)識(shí),但認(rèn)識(shí)東西的確很少。 也可以從另一方面去理解,曾經(jīng)看一個(gè)電視節(jié)目,有個(gè)嘉賓在錄制的過(guò)程中,突然抬起頭對(duì)著天花板仰望,然后主持人很驚訝問(wèn)他在干嗎?他說(shuō):我在思考宇宙有沒(méi)有盡頭?主持人接著問(wèn):那宇宙有沒(méi)有盡頭?他淡然的回答道:有就有,沒(méi)有就沒(méi)有。當(dāng)然觀眾和主持人都笑作一團(tuán),你會(huì)笑嗎?透過(guò)現(xiàn)象看本質(zhì),其實(shí)這個(gè)思想和老莊的思想很合拍,扯遠(yuǎn)了。 HTTP即超文本傳送協(xié)議。 超文本傳輸協(xié)議 (HTTP-Hypertext transfer protocol) 是一種詳細(xì)規(guī)定了瀏覽器和萬(wàn)維網(wǎng)服務(wù)器之間互相通信的規(guī)則,通過(guò)因特網(wǎng)傳送萬(wàn)維網(wǎng)文檔的數(shù)據(jù)傳送協(xié)議。 從定義中看出HTTP是一種協(xié)議,超文本傳輸協(xié)議,那什么是超文本?和我們所說(shuō)的富文本有些區(qū)別,超文本也是一種文本格式,那可以把它看成是文本與文本之間關(guān)聯(lián)而組成的網(wǎng)狀文本,有點(diǎn)類似于面向?qū)ο笾袑?duì)象的集合,雖然是對(duì)象的集合,但本身也是一個(gè)對(duì)象。 HTTP協(xié)議有下面三個(gè)基本特點(diǎn):
相對(duì)于Web API來(lái)說(shuō),HTTP不只是為了生成Web頁(yè)面,它也是一個(gè)強(qiáng)大的平臺(tái)建設(shè)公開(kāi)服務(wù)和數(shù)據(jù)的API。HTTP是簡(jiǎn)單、 靈活和無(wú)處不在,因此幾乎任何平臺(tái)都可以有一個(gè)HTTP庫(kù),因此,HTTP服務(wù)可以到達(dá)范圍廣泛的客戶端,包括瀏覽器、移動(dòng)設(shè)備和傳統(tǒng)的桌面應(yīng)用程序。 RESTfulRESTful架構(gòu)概念是Fielding提出的,F(xiàn)ielding這號(hào)人物就是上面HTTP協(xié)議的主要設(shè)計(jì)者之一。我們先看下RESTful這個(gè)詞,ful是跟在名詞之后,表示程度,什么什么的,例如helpful樂(lè)于助人的,因此我們可以看出符合REST的架構(gòu)就可以稱為RESTful,接著我們看下REST,全稱為“Representational State Transfer”,意為“表現(xiàn)層狀態(tài)轉(zhuǎn)化”。 在符合架構(gòu)原理的前提下,理解和評(píng)估以網(wǎng)絡(luò)為基礎(chǔ)的應(yīng)用軟件的架構(gòu)設(shè)計(jì),得到一個(gè)功能強(qiáng)、性能好、適宜通信的架構(gòu)。 -Fielding 這是Fielding在論文中所提到的,對(duì)于REST雖說(shuō)是架構(gòu),但如果深入一點(diǎn),就像是HTTP協(xié)議一樣,可以看成一種規(guī)則或是協(xié)議。我們從一個(gè)地點(diǎn)到另一個(gè)地點(diǎn),可以坐汽車、高鐵、飛機(jī)等,對(duì)于REST就像是其中的一種交通方式,但REST的根本是HTTP協(xié)議,也就是說(shuō)REST是基于HTTP協(xié)議的,這點(diǎn)就像坐汽車必須要有公路,坐高鐵必須要有鐵路是一樣的道理,有時(shí)候?yàn)槭裁催x用REST,就像我們從南京到徐州,選擇坐高鐵而不選擇坐飛機(jī)一樣。 上面這個(gè)比喻可能不太恰當(dāng),但是思想都是相同的,如果有可能的話可以看下一些哲學(xué)方面的書(shū),像莊子的道德經(jīng),畢竟編程是哲學(xué)或是藝術(shù)的另一類體現(xiàn),又扯遠(yuǎn)了。 “Representational State Transfer”我們分解下:
通過(guò)上面的理解,可以總結(jié)下什么是RESTful架構(gòu):
創(chuàng)建Web API關(guān)于Web API的實(shí)現(xiàn)方式,.net提供了一套機(jī)制就是ASP.NET MVC API,類似MVC的方式,實(shí)現(xiàn)起來(lái)很簡(jiǎn)單,也不需要你去關(guān)注HTTP和RESTful的一些東西,當(dāng)你去新建項(xiàng)目的時(shí)候,一切東西.net都幫你搞定了,是好還是不好?只能呵呵笑過(guò)。 下面我們就一步一步的創(chuàng)建一個(gè)ASP.NET MVC API。 1,新建ASP.NET MVC WebMvc的ApiDemo程序,選擇Web API模板類型。
2,創(chuàng)建News模型,雖然創(chuàng)建的是MVC項(xiàng)目,但是我們一般只用到控制器和模型。 1 public class News
2 {
3 /// <summary>
4 /// 新聞ID
5 /// </summary>
6 public int Id { get; set; }
7 /// <summary>
8 /// 新聞標(biāo)題
9 /// </summary>
10 public string Title { get; set; }
11 /// <summary>
12 /// 新聞內(nèi)容
13 /// </summary>
14 public string Content { get; set; }
15 /// <summary>
16 /// 新聞作者
17 /// </summary>
18 public string Author { get; set; }
19 /// <summary>
20 /// 發(fā)布新聞時(shí)間
21 /// </summary>
22 public DateTime CreateTime { get; set; }
23 }
3,創(chuàng)建數(shù)據(jù)模擬類NewsRepository,用于查詢數(shù)據(jù)。 1 public class NewsRepository
2 {
3 public IEnumerable<News> GetAllNews()
4 {
5 News[] news = new News[]
6 {
7 new News { Id = 1, Title="新聞標(biāo)題1", Content="新聞內(nèi)容1", Author="xishuai", CreateTime=DateTime.Now },
8 new News { Id = 2, Title="新聞標(biāo)題2", Content="新聞內(nèi)容2", Author="xishuai", CreateTime=DateTime.Now },
9 new News { Id = 3, Title="新聞標(biāo)題2", Content="新聞內(nèi)容3", Author="xishuai", CreateTime=DateTime.Now }
10 };
11 return news;
12 }
13 }
4,創(chuàng)建NewsController控制器,注意的是:新建控制器的時(shí)候,模板選擇“空 API 控制器”,與MVC控制器不同的是,API控制器繼承ApiController基類。在我們新建ApiDemo的MVC項(xiàng)目的時(shí)候,自動(dòng)生成了一個(gè)ValuesController API控制器,打開(kāi)后我們發(fā)現(xiàn),有很多自動(dòng)生成的方法,請(qǐng)求方式就是我們上面說(shuō)GET、POST、PUT和DELETE的四種HTTP請(qǐng)求方式,我們這邊做一個(gè)Get的,獲取全部新聞或是指定新聞ID獲取,返回結(jié)果格式為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 }
這里面主要用到兩個(gè)轉(zhuǎn)化類:XmlContent和SimpleXmlConverter,有關(guān)這兩個(gè)類的詳細(xì)代碼可以下載Demo看下。
5,路由配置,Web API和MVC的路由配置很相似,主要區(qū)別是Web API使用HTTP方法而不是URI路徑來(lái)選擇動(dòng)作,路由文件WebApiConfig,如下: 1 config.Routes.MapHttpRoute(
2 name: "DefaultApi",
3 routeTemplate: "api/{controller}/{action}/{id}",
4 defaults: new { id = RouteParameter.Optional }
5 );
其實(shí)寫(xiě)到這里創(chuàng)建Web API的代碼就差不多了,當(dāng)然復(fù)雜的操作可以擴(kuò)充,用.net開(kāi)發(fā)就是這么簡(jiǎn)單,只要完成業(yè)務(wù)邏輯就行了,呵呵。 調(diào)用Web API調(diào)用Web API有很多種方式,js可以調(diào)用,就像我們寫(xiě)MVC請(qǐng)求數(shù)據(jù)一樣,這種是同一域下調(diào)用,Web API也是這種方式就沒(méi)什么意思了,如果使用js調(diào)用就必須跨域操作,這邊我們使用HttpClient的方式。 1,新建控制臺(tái)應(yīng)用程序-ClientDemo。
2,安裝Web API 客戶端庫(kù),工具-程序包管理器-程序包管理控制平臺(tái),輸入命令:Install-Package Microsoft.AspNet.WebApi.Client 上面新建的ClientDemo項(xiàng)目.net framework版本是4.0,安裝HttpClient的時(shí)候報(bào)下面錯(cuò)誤:
.net framework版本改為4.5就安裝成功了,難道HttpClient只支持4.5以上?查了下MSDN,HttpClient確實(shí)只支持.net framework4.5,難道以前程序如果使用HttpClient要把.net framework改成4.5?有點(diǎn)郁悶。
4,創(chuàng)建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("新聞標(biāo)題:" + node.SelectSingleNode("Title").InnerText);
22 Console.WriteLine("新聞內(nèi)容:" + node.SelectSingleNode("Content").InnerText);
23 Console.WriteLine("作者:" + node.SelectSingleNode("Author").InnerText);
24 Console.WriteLine("新聞發(fā)布時(shí)間:" + node.SelectSingleNode("CreateTime").InnerText);
25 Console.WriteLine("======================");
26 }
27 Console.ReadKey();
28 }
29 }
Main 函數(shù)調(diào)用一個(gè)名為RunAsync的異步方法,然后會(huì)阻止,直到RunAsync完成。許多的HttpClient方法是異步,因?yàn)樗麄儓?zhí)行網(wǎng)絡(luò) i/o 操作。MediaTypeWithQualityHeaderValue是定義傳輸格式,如果使用json則為“application/json”,這邊要與Web API格式一致,XML獲取使用的是GetStringAsync方法,然后轉(zhuǎn)換為XmlDocument,網(wǎng)上找了一種GetStreamAsync方法獲取,通過(guò)Stream轉(zhuǎn)化為字符串,但是轉(zhuǎn)化后的字符串為空。 上面調(diào)用Web API的是獲取全部新聞,如果調(diào)用通過(guò)新聞ID獲取新聞,GetStringAsync的方法參數(shù)只需要改為“api/News/GetNewsByID/新聞ID”就可以了。 5,關(guān)于Web API的發(fā)布問(wèn)題,這個(gè)問(wèn)題花了不少時(shí)間,一個(gè)一個(gè)問(wèn)題出現(xiàn)及解決,首先我們先不急著調(diào)用,先發(fā)布瀏覽,如果瀏覽器瀏覽沒(méi)問(wèn)題的話再調(diào)用。Web API的發(fā)布和MVC差不多,需要注意下面幾點(diǎn):
運(yùn)行截圖及Demo下載Web API瀏覽器請(qǐng)求截圖:
Web API發(fā)布運(yùn)行截圖:
客戶端調(diào)用運(yùn)行截圖:
Demo下載地址:http://pan.baidu.com/s/1hqwtQEK HTTP請(qǐng)求的四種方法(PUT、GET、POST和DELETE)本篇只是講到GET,HTTP的數(shù)據(jù)傳輸格式(json、xml等)也只是說(shuō)了XML,但都是大同小異,舉一反三可得。 如果你覺(jué)得本篇文章對(duì)你有所幫助,請(qǐng)點(diǎn)擊右下部“推薦”,^_^
|
|
|
來(lái)自: ThinkTank_引擎 > 《Demo》