[ASP.NET]谈谈REST与ASP.NET Web API
13天的假期结束,赶紧回来充电了
本节目录
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协议
1 2 3 4 5 6 7 8 9 | 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部分组成.
1 2 3 4 5 6 7 8 9 10 11 12 | 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类
1 2 3 4 5 | public class Contact { public string Id { get ; set ; } public string Name { get ; set ; } } |
创建控制器
在WebApi项目中,引用System.Web.Http类库并创建API控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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类库并实现寄宿
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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寄宿非常简单,只要注册好路由数据即可
建立项目
- WebHost:一个空的Web项目(引用Model和WebApi项目)
注册路由
新建Global文件,注册HttpRoute
1 2 3 4 5 6 7 8 9 10 | 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是基于HTTP的,所以对于开发人员,就像普通请求网站数据一样
- jQuery
- MVVM/MVC框架的JS,AngularJS,Knockout.js
- 后台可以使用HttpClient、WebClient、HttpWebRequest等
这里演示一个HttpClient完整的例子,对于异步有疑问,可阅读我的博客:[C#] 谈谈异步编程async await
新建一个控制台项目即可,实现Program类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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借用了MVC的设计,以Controller形式定义服务,Action代表具体的操作.
Web API借助于URL路由得到控制器,再根据路由对象,通过http方法找到对应的action.(实际上,如果根据url解析不到action的时候,才会通过http方法)
路由注册
1 2 3 4 5 | 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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验