[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

posted @ 2015-10-09 10:31  Never、C  阅读(11874)  评论(37编辑  收藏  举报