ASP.NET WEB API的適用情境第一個執行個體

來源:互聯網
上載者:User
在我前一篇部落格中已經給各位簡單介紹了HTTP協議與RestFul API的關係,以及一些基本的HTTP協議知識,在這些知識的鋪墊下,今天,我們一起來討論一下WEB API的適用情境,然後寫我們第一個WEB API介面,並示範如何對其進行簡單調用。

很多人都很迷惑,既然有了WCF為什麼還要有WEB API?WEB API會不會取代WCF?

就我的看法,WCF提供的是一種RPC實現的集合,WCF的設計更多地考慮了SOA的情境,以及各種RPC的問題。很多人也會說,RestFul API也是一種RPC啊,並且WCF中也有關於RestFul 的實現啊。很多資料中RPC和RestFul在風格概念上是有一些區別的,其實我覺得這兩者的區別比較主觀,過度糾結這些就學院派了;我主要關注了實際使用上的一些問題,在WCF中,支援的協議很多,WS-*系列協議,以及一些更簡潔的協議,其中提供了一些專用通訊協定的效能是非常高的,並且WCF還提供了服務發現等功能,我認為WCF更適合內部系統間的高效能調用,社區中也有其他一些RPC方案可以選擇,例如gRPC,Avor,thrift都是和WCF定位相同的產品;而WEB API是關注於HTTP RestFul風格的產品,在此基礎上,任何語言、任何終端都能非常容易地進行對接,並且能利用非常成熟的各種HTTP基礎設施和解決方案來進行開發、調試、負載平衡、內容分發。所以,WEB API是一種針對HTTP的,偏重於快速開發RestFul風格開放式API的開發架構。目前看來,他並不能取代WCF,他們各有適合的情境,不能認為WEB API是WCF的替代產品。

OK,現在我們來開發第一組WEB API介面!使用VS2012以後的版本都有現成的WEB API建立模板,大家跟著建立就好了,建立出來後,項目中會有MVC、WEB API的項目,WEB API對MVC有依賴,不能單獨建立!而WEB API和MVC都是利用類似的路由機制,所以在預設路由中,WEB API 使用


/api/{controller}/{id}

作為路由,添加了/api/節以區分MVC和web api。

接下來,我們添加一個WEB API的Controller,取名為PersonController,他繼承於ApiController;在建立這個Controller的時候,我們就定義了一種資源:Person,在PersonController裡的所有操作均圍繞著Person這個資源來的。接下來我們開始定義一組增刪改查操作。

在Web API中,預設路由採用了一種約定:根據謂詞來進行路由,而方法名的首碼就是調用該方法對應使用的HTTP謂詞。程式碼範例如下:


/// <summary>    /// Person 為資源,對Person進行的一組操作    /// </summary>    public class PersonController : ApiController    {        private static List<Person> _personLst = new List<Person>();               /// <summary>        /// 擷取一個Person        /// </summary>        /// <param name="id">Person的ID</param>        /// <returns>Person</returns>        public Person GetPerson(long id)        {            return _personLst.Find(x => x.Id == id);        }         /// <summary>        /// 添加一個Person        /// </summary>        /// <param name="person">Person</param>        public void PostAddPerson(Person person)        {            _personLst.Add(person);        }         /// <summary>        /// 修改一個        /// </summary>        /// <param name="id">Person Id</param>        /// <param name="person">新</param>        public void PutModifyPerson(long id, Person person)        {            var p = _personLst.Find(x => x.Id == id);            p.Age = person.Age;            p.Name = person.Name;            p.Sex = person.Sex;        }         /// <summary>        /// 刪除一個Person        /// </summary>        /// <param name="id">Person ID</param>        public void DeletePerson(long id)        {            _personLst.RemoveAll(x => x.Id == id);        }}

一個簡單的針對資源的CRUD操作的API就好了,不用解析輸入,不用拼接輸出,就是那麼簡單!讓我們來遛一遛!

發送請求:謂詞為POST,語義建立Person,Person描述在Body裡,head中聲明了Body通過Json序列化。

收到響應:響應碼204,屬於2XX類型執行成功,Body裡沒有資料

發送請求:謂詞為GET,語義為查詢Person資源,Id為1的,head中聲明希望接收使用XML序列化的資料

收到響應:響應碼為200,執行成功,Body中有資料,資料使用XML序列化

發送請求:謂詞為PUT,語義為修改ID為1的Person資源,修改內容在Body中,Content-Type標明Body使用Json序列化,在Body中我們將Name修改為Test1Changed

收到響應,響應碼為204,執行成功

發送請求:謂詞為GET,語義為查詢ID為1的Person資源,Accept標明希望接收到Json資料

收到響應:可以看到Body為使用Json序列化的內容,Name屬性已經變更為Test1Changed

發送請求:謂詞為DELETE,語義為刪除ID為1的Person資源

收到響應:響應碼204,執行成功

發送請求:謂詞為GET,語義為查詢ID為1的Person資源,Accept標明希望接收到Json資料

收到響應:響應碼為200,執行成功,響應內容為null,資源已刪除

這就是我用Fiddler來發送、調用的一組RestFul介面,大家可以看到,整個調用過程使用到了HTTP的語義,用到了謂詞路由、內容協商。在增、刪、改操作中,我都是使用void作為傳回值,根據HTTP Code 判斷,大家也可以自訂一些返回資料來做出更進一步的操作描述。

在寫了這些API後,我們需要在程式中調用,我以C#為例寫一組對這些介面調用的實現。在C#中,傳統調用HTTP介面一般有兩種辦法: WebRequest/WebResponse組合的方法調用和WebClient類進行調用。第一種方法抽象程度較低,使用較為繁瑣;而WebClient主要面向了WEB網頁情境,在類比Web操作時使用較為方便,但用在RestFul情境下卻比較麻煩,在Web API發布的同時,.NET提供了兩個程式集:System.Net.Http和System.Net.Http.Formatting。這兩個程式集中最核心的類是HttpClient。在.NET4.5中帶有這兩個程式集,而.NET4需要到Nuget裡下載Microsoft.Net.Http和Microsoft.AspNet.WebApi.Client這兩個包才能使用這個類,更低的.NET版本就只能表示遺憾了只能用WebRequest/WebResponse或者WebClient來調用這些API了。

在使用中,System.Net.Http這個程式集提供了HttpClient類以及相關的HTTP調用,而System.Net.Http.Formatting提供了一些針對HttpClient的協助擴充,更好地支援了內容協商、Content建立等功能。下面我就和大家一起寫一下這個例子:

我們建立一個控制台程式:

代碼如下:


public class Person    {        public long Id { get; set; }        public string Name { get; set; }         public int Age { get; set; }         public string Sex { get; set; }         public override string ToString()        {            return $"Id={Id} Name={Name} Age={Age} Sex={Sex}";        }    }     class Program    {        static void Main(string[] args)        {            var client = new HttpClient();             client.BaseAddress = new Uri("http://localhost:22658/"); //基本的API URL            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //預設希望響應使用Json序列化              Run(client);             Console.ReadLine();         }         static async void Run(HttpClient client)        {            var result = await AddPerson(client);            Console.WriteLine($"添加結果:{result}"); //添加結果:true             var person = await GetPerson(client);            Console.WriteLine($"查詢結果:{person}"); //查詢結果:Id=1 Name=test Age=10 Sex=F             result = await PutPerson(client);            Console.WriteLine($"更新結果:{result}"); //更新結果:true             result = await DeletePerson(client);            Console.WriteLine($"刪除結果:{result}"); //刪除結果:true        }         static async Task<bool> AddPerson(HttpClient client)        {            return await client.PostAsJsonAsync("api/Person", new Person() { Age = 10, Id = 1, Name = "test", Sex = "F" }) //向Person發送POST請求,Body使用Json進行序列化                                     .ContinueWith(x => x.Result.IsSuccessStatusCode);  //返回請求是否執行成功,即HTTP Code是否為2XX        }         static async Task<Person> GetPerson(HttpClient client)        {            return await await client.GetAsync("api/Person/1") //向Person發送GET請求                .ContinueWith(x => x.Result.Content.ReadAsAsync<Person>(                              //擷取返回Body,並根據返回的Content-Type自動匹配格式化器還原序列化Body                    new List<MediaTypeFormatter>() {new JsonMediaTypeFormatter()/*這是Json的格式化器*/                                                    ,new XmlMediaTypeFormatter()/*這是XML的格式化器*/}));         }         static async Task<bool> PutPerson(HttpClient client)        {            return await client.PutAsJsonAsync("api/Person/1", new Person() { Age = 10, Id = 1, Name = "test1Change", Sex = "F" }) //向Person發送PUT請求,Body使用Json進行序列化                                    .ContinueWith(x => x.Result.IsSuccessStatusCode);  //返回請求是否執行成功,即HTTP Code是否為2XX        }         static async Task<bool> DeletePerson(HttpClient client)        {            return await client.DeleteAsync("api/Person/1") //向Person發送DELETE請求                .ContinueWith(x => x.Result.IsSuccessStatusCode); //返回請求是否執行成功,即HTTP Code是否為2XX        }}

這就完成了這組API的調用,是不是非常簡單方便?HTTPClient使用全非同步方法,並且他有良好的擴充性,我會在之後的部落格中再聊這個問題。

OK,到此為止一組簡單的Restful API和C#的調用用戶端就完成了,但這隻是開始,Web API是一個很強大的架構,他的擴充點非常豐富,這些擴充能為我們的開發提供很多的協助,下一篇博文我將為大家帶來WEB API中Filter的使用。

博文中如有不正確的地方歡迎大家指正。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.