[ASP.NET]談談REST與ASP.NET Web API


13天的假期結束,趕緊回來充電了

 

本節目錄

 

Web API簡介

REST

REST是“REpresentational State Transfer”的縮寫,可以翻譯成“表現狀態轉換”.

REST是一種軟件架構風格,與技術無關,但是大部分基於REST風格的Web服務都是基於HTTP的

(雖然WCF在3.5以后支持REST,但是WCF太龐大了,Web API更適合做REST架構)

 

SOAP與REST

SOAP Web API采用RPC(面向方法Remote Procedure Call)風格,它采用面向功能的架構,所以在設計之初首先需要考慮的是提供怎樣的功能。

RESTful Web API采用ROA(面向資源Resouce Oriented Architecture)架構,所以在設計之初首先需要考慮的是有哪些資源可供操作。

 

HTTP協議

HTTP采用簡單的請求/響應模式的消息交換旨在實現針對某個Web資源的某種操作。

至於針對資源的操作類型,不外乎CRUD(Create、Retrieve、Update和Delete)而已。

一個HTTP請求除了利用URI標志目標資源之外,還需要通過HTTP方法指名針對資源的操作類型。

HTTP方法:包括GET(查)、POST(增)、PUT(改)、DELETE(刪)、HEAD、OPTIONS、TRACE、CONNECTION和PATCH等

 

HTTP協議

GET http://neverc.cn/ HTTP/1.1
Host: neverc.cn
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.15 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: 

第1行是HTTP的3個基本屬性,method,uri,vesion

其他都是HTTP的請求報頭header,http定義很多原生的header,也可以添加自定義header(實際就是鍵值對)

除了報頭,一個HTTP請求還可以包括一個請求主體內容,可以是任意格式.

 

與HTTP請求一樣,HTTP響應也是由報頭和報文2部分組成.

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 5.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 18 Sep 2015 05:39:50 GMT
Content-Length: 12003

<!DOCTYPE html>

第1行是vesion和statu(除了200 OK外,常見的有401 Not Authorized、404 Not Found)

第3行Content-Type表示媒體(或者叫資源/數據)類型.

  • text/html:HTML格式的文檔。
  • text/xml(application/xml):XML格式的文本。
  • text/json(application/json): JSON格式的文本。
  • image/gif(image/jpeg、image/png):GIF(JPEG、PNG)格式的圖片。
  • audio/mp4(audio/mpeg、audio/vnd.wave):MP4(MPEG、WAVE)格式的音頻文件。
  • video/mp4(video/mpeg、video/quicktime):MP4(MPEG、QUICKTIME)格式的視頻文件。

 

自我寄宿

建立項目

  • Model:一個類庫項目,定義實體
  • WebApi:一個類庫項目,定義API控制器(引用Model項目)
  • SelfHost:一個控制台項目,寄宿API服務(引用WebApi項目)

涉及到的引用的程序集

 

創建實體

在Model項目中,新建一個Contact類

    public class Contact
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

 

創建控制器

在WebApi項目中,引用System.Web.Http類庫並創建API控制器

    public class ContactsController : ApiController
    {
        #region Data
        static readonly List<Contact> contacts;
        static int counter = 2;
        static ContactsController()
        {
            contacts = new List<Contact>
            {
                new Contact{Id = "001",Name = "張三"},
                new Contact{Id = "002",Name = "李四"}
            };
        }
        #endregion
        public IEnumerable<Contact> Get(string id = null)
        {
            return from contact in contacts
                   where contact.Id == id || string.IsNullOrEmpty(id)
                   select contact;
        }
        public void Post(Contact contact)
        {
            //多線程並發處理
            Interlocked.Increment(ref counter);
            contact.Id = counter.ToString("D3");
            contacts.Add(contact);
        }
        public void Put(Contact contact)
        {
            contacts.Remove(contacts.First(c => c.Id == contact.Id));
            contacts.Add(contact);
        }
        public void Delete(string id)
        {
            contacts.Remove(contacts.First(c => c.Id == id));
        }
    }

 

自我寄宿

在SelfHost中,引用System.Web.Http、System.Net.Http、System.Web.Http.SelfHost類庫並實現寄宿

        static void Main(string[] args)
        {
            //對於SelfHost來說,HttpController類型的解析在默認情況下只會針對加載到當前應用程序域中的程序集列表
            //通過手工加載,讓該程序集加載到當前應用程序域中。
            Assembly.Load("WebApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
            var configuration = new HttpSelfHostConfiguration("http://localhost/selfhost");
            using (var httpServer = new HttpSelfHostServer(configuration))
            {
                httpServer.Configuration.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional });
                httpServer.OpenAsync().Wait();
                Console.WriteLine("寄宿Web API服務成功");
                Console.Read();
            }
        }

 

測試

運行SelfHost控制台,瀏覽器訪問http://localhost/selfhost。

注意:(由於此處會注冊http.sys,所以需要管理員身份運行VS)

 

 

IIS寄宿

使用IIS寄宿非常簡單,只要注冊好路由數據即可

 

建立項目

  • WebHost:一個空的Web項目(引用Model和WebApi項目)

 

注冊路由

新建Global文件,注冊HttpRoute

    public class Global : HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            GlobalConfiguration.Configuration.Routes.MapHttpRoute(
              name: "DefaultApi",
              routeTemplate: "api/{controller}/{id}",
              defaults: new { id = RouteParameter.Optional });
        }
    }

 

測試

運行WebHost項目,瀏覽器訪問http://~/api/Contacts。

 

調用Web API

因為Web API是基於HTTP的,所以對於開發人員,就像普通請求網站數據一樣

  • jQuery
  • MVVM/MVC框架的JS,AngularJS,Knockout.js
  • 后台可以使用HttpClient、WebClient、HttpWebRequest等

 

這里演示一個HttpClient完整的例子,對於異步有疑問,可閱讀我的博客:[C#] 談談異步編程async await

 

新建一個控制台項目即可,實現Program類:

static HttpClient httpClient = new HttpClient();
        static void Main(string[] args)
        {
            //由於HttpClient類中的方法大部分為異步
            //Main方法不支持Async關鍵字
            //故新建一個方法,使其同步運行
            Process();
            Console.Read();
        }

        async static void Process()
        {
            //獲取當前聯系人列表
            ListContacts();

            //添加新的聯系人
            var contact = new Contact { Name = "王五" };
            await httpClient.PostAsJsonAsync("http://localhost/selfhost/api/contacts", contact);
            Console.WriteLine("添加新聯系人“王五”:");
            ListContacts();

            //修改現有的某個聯系人
            var response = await httpClient.GetAsync("http://localhost/selfhost/api/contacts/001");
            contact = (await response.Content.ReadAsAsync<IEnumerable<Contact>>()).First();
            contact.Name = "趙六";
            await httpClient.PutAsJsonAsync("http://localhost/selfhost/api/contacts/001", contact);
            Console.WriteLine("修改聯系人“001”信息:");
            ListContacts();

            //刪除現有的某個聯系人
            await httpClient.DeleteAsync("http://localhost/selfhost/api/contacts/002");
            Console.WriteLine("刪除聯系人“002”:");
            ListContacts();
        }

        async static void ListContacts()
        {
            var response = await httpClient.GetAsync("http://localhost/selfhost/api/contacts");
            IEnumerable<Contact> contacts = await response.Content.ReadAsAsync<IEnumerable<Contact>>();
            Console.WriteLine("當前聯系人列表:");
            foreach (Contact contact in contacts)
            {
                Console.WriteLine("{0,-6}{1,-6}", contact.Id, contact.Name);
            }
            Console.WriteLine();
        }

 

Web API原理

Web API借用了MVC的設計,以Controller形式定義服務,Action代表具體的操作.

Web API借助於URL路由得到控制器,再根據路由對象,通過http方法找到對應的action.(實際上,如果根據url解析不到action的時候,才會通過http方法)

 

路由注冊

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

由於在模板中沒有定義action,所以只能通過httpmethod來找action.(並且是根據方法前綴匹配即可)

 

通過瀏覽器api/Contacts查看的時候,會返回一個xml格式的數據.

實際上,webapi是先檢查accept,從左到右,去匹配序列化器,如果沒有匹配到則使用默認的json序列化器.

 

 

管道式設計

Web API也采用了管道式設計,這是一個不同於MVC的管道.雖然很多地方和MVC相似.

Route對象為HttpRoute

Handle對象為HttpControllerHandler(由於實現了IHttpAsyncHandler接口,所以默認走BeginProcessRequest異步方法)

 

 

擴展:

如果你的網站部署在IIS上,直接Nuget下載 Install-Package Microsoft.AspNet.WebApi.WebHost 即可使用Web API

 

本文地址:http://neverc.cnblogs.com/p/4603935.html 

參考:http://www.cnblogs.com/artech/p/how-asp-net-web-api-works.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM