web APIS

WEB API系列:

 

           不少人都很迷惑,既然有了WCF爲何還要有WEB API?WEB API會不會取代WCF?html

       就個人見解,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的替代產品。web

       OK,如今咱們來開發第一組WEB API接口!使用VS2012之後的版本都有現成的WEB API建立模板,你們跟着建立就行了,建立出來後,項目中會有MVC、WEB API的項目,WEB API對MVC有依賴,不能單首創建!而WEB API和MVC都是利用相似的路由機制,因此在默認路由中,WEB API 使用json

/api/{controller}/{id}

 

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

       接下來,咱們添加一個WEB API的Controller,取名爲PersonController,他繼承於ApiController;在建立這個Controller的時候,咱們就定義了一種資源:Person,在PersonController裏的全部操做均圍繞着Person這個資源來的。接下來咱們開始定義一組增刪改查操做。app

       在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序列化。async

收到響應:響應碼204,屬於2XX類型執行成功,Body裏沒有數據ide

 

發送請求:謂詞爲GET,語義爲查詢Person資源,Id爲1的,head中聲明但願接收使用XML序列化的數據post

收到響應:響應碼爲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

        }

}
相關文章
相關標籤/搜索