使用ASP.NET web API创建REST服务(二)
2015-07-13 07:50
791 查看
CreatingaRESTserviceusingASP.NETWebAPI
Aservicethatiscreatedbaseduponthearchitectureof
RESTiscalledasRESTservice.AlthoughRESTlooksmoreinclinedtowebandHTTPitsprinciplescanbeappliedtootherdistributedcommunicationsystemsalso.OneoftherealimplementationofRESTarchitectureistheWorldWideWeb(WWW).RESTbased
servicesareeasytocreateandcanbeconsumedfromawidevarietyofdevices.
REST(REpresentationalStateTransfer,表述性状态转移)。REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。
REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web服务,包括使用不同语言编写的客户端如何通过HTTP处理和传输资源状态。如果考虑使用它的Web服务的数量,REST近年来已经成为最主要的Web服务设计模式。事实上,REST对Web的影响非常大,由于其使用相当方便,已经普遍地取代了基于SOAP和WSDL的接口设计。
TherearemanyAPIsavailableindifferentlanguagestocreateandconsumeRESTservices.The
ASP.NETMVCbeta4comeswithanewAPIcalled
ASP.NETWebAPItocreateandconsumeRESTservices.WhilecreatingRESTservicesitisimportanttofollowtherulesandstandardsoftheprotocol(HTTP).Withoutknowingtheprinciplesof
RESTitiseasytocreateaservicethatlooksRESTfulbuttheyareultimatelyanRPCstyleserviceoraSOAP-RESThybridservice.InthisarticlewearegoingtoseehowtocreateasimpleRESTserviceusingtheASP.NETWebAPI.
ASP.NETMVCbeta4附带了API开发功能,同时可以调用ASP.NET
WebAPI来创建和使用REST服务。创建其他服务时很重要的是要遵循标准的协议(HTTP)。
在这篇文章我们来看看如何创建一个简单的ASP.NETWebAPIREST服务,并且调用它。
开发工具:VisualStudio2013
创建步骤:
然后再Model中创建一个类Person:
+ViewCode?
在这里您可能会在您认为合理的框架中使用WebAPI,所以我们只从原理上来描述它,不拘泥于具体的实现方式和设计模式。
接着在Model中创建一个接口IPersonRepository
+ViewCode?
然后,让我们去实现它。同样在Model中创建一个实现类PersonRepository
+ViewCode?
在这个实现中不管您将采取任何数据来源XML,文件或者其他持久化存储,我们都可以返回一个实现了IEnumerable接口的列表,从而消除数据来源的差异性。
acceptsincomingHTTPrequestsandprocessesaccordingly.However,thestandardMVCControllerreturnsaView,whiletheWebApicontrollerreturnsdata.
特别值得注意的是,WebApicontroller会检查接受HTTP请求头部。然后将NET对象序列化为适当的返回数据类型(XML或JSON)。
在Controllers文件夹上右键选择添加—>控制器,然后如下图选择
命名为PersonController。
现在您可以方便的在这里添加任何GURD代码。我们一起来分析一个具体实现:
+ViewCode?
第一句代码可以说是实例化一个数据访问类,而我们要做的是根据ID返回要查询的Person对象,通过调用对应方法可以实现。注意观察这个方法是以Get方式开头,而这个方法包含一个id参数,这个方法会匹配/api/PersonController/id的请求,而请求中的参数id会自动转换为int类型
如果没有找到相应id的联系人,则会抛出一个自定义HttpResponseMessage的异常,这个异常是指向的404异常,表示请求资源不存在。实际项目中,我们是非常有必要返回一些和操作对应的异常信息的。
完整代码如:
+ViewCode?
Aswehavealludedtopreviously,acoretenetofMVCistofavorConventionoverConfiguration.Intermsofourcontrollerclass,whatthismeansisthattheASP.NET/MVCruntimeestablishescertaindefaultbehaviorswhichrequirenoadditionalconfiguration,unlessyouwanttochangethem.Initially,formeanyway,thiswasalsoasourceofconfusion,astheruntimeappearedtoperformsufficient"magic"thatIdidn'tknowwhatwashappening.
当然其中一个非常重要的WebAPI规范就是HTTP谓词的映射,如GET、POST、PUT、DELETE。那么正如我们上面所述,我们的动作也遵循了这个规范。原因是在ASP.NETWebAPI,一个controller是一个class(类)以处理HTTP请求(requests)。在controller里所有的公开方法(publicmethods)都称为Action方法或简称Action。当WebAPIFramework接收到一个请求,它路由请求到一个Action。
每个实体(entry)在路由表里都包含一个路由样板(routetemplate)。WebAPI的路由样板默认是"api/{controller}/{id}",此样板里,"api"是文字路径片段,{controller}和{id}是定位参数。
当WebAPIFramework接收到一个HTTP请求,它会去尝试比对URI对路由表的路由样板列表,如果没有符合的路由,Client会收到一个404错误。例如,以下URI会符合默认路由:
·/api/Person
·/api/Person/1
路由表定义如:
?
例如,一个GET请求,WebAPI会查看那一个action是以"Get..."开头,比如"GetContact"或"GetAllContacts"。同样规则适用在GET,POST,PUT,DELETE方法。你也能在controller里使用属性(attributes)去启用其他HTTP方法。
以下是一些可能HTTP请求及其含义:
当然,我们可以根据自己的实际需要修改这个路由表,如:
?
那么根据ID查询某个人就需要这样发送请求:
/api/person/GetPersonByID/1
也可以访问到需要的资源。
Wecanre-writeourclientexamplestoutilizeaPersonclassifitsuitsourneeds,andpassinstancesofPersontoandfromourAPIprojectindirectlythroughserialization.Ourcoreclientmethods,re-written,looklikethis:
我们以控制台程序为例,新建一个控制台项目,假设命名为:RestApiClient
添加第一个类Person:
+ViewCode?
至于为什么要在这里还要添加一个Person类,我们可以想象WEBAPI机制,它是类似于WebService的一种远程数据调用消息交换机制,服务器上使用的类本地是没有的,为了类型和序列化方便通常还要在消费端再次定义一次,加入您将消费放在服务端如以WCF的形式来进行,真正的客户端通过同步/异步请求来获取资源,那么另当别论。
然后新建一个类用来发送请求给WEBAPI,我们再次来分析这个类里面写些什么,列举一个方法:
+ViewCode?
可以看出返回的是JArray格式。说明如下:
使用JSON前,需要引用Newtonsoft.Json的dll和usingNewtonsoft.Json.Linq的命名空间。LINQtoJSON主要使用到JObject,JArray,JProperty和JValue这四个对象,JObject用来生成一个JSON对象,简单来说就是生成"{}",JArray用来生成一个JSON数组,也就是"[]",JProperty用来生成一个JSON数据,格式为key/value的值,而JValue则直接生成一个JSON值。下面我们就用LINQtoJSON返回上面分页格式的数据。
下面就是定义一个HttpClient去发送一个GET请求给指定WEBAPI,然后利用HttpResponseMessage接收返回的JSON数据。
完整代码如:
+ViewCode?
最不值钱的就是最终调用了,在Program类的Main方法中调用代码如下:
+ViewCode?
PS:
这里我偷了个懒,把他们写成一个部分类了,实际应该怎么写你懂得…
如果报每个方法最后一句出错,请加引用:"System.Net.Http.Formatting",可以在这里找到C:\ProgramFiles(x86)\MicrosoftASP.NET\ASP.NETMVC4\Assemblies\System.Net.Http.Formatting.dll真实的想法是实在不想加这个引用,原因请看下面。
另外遗憾的一点是我们对服务的消费操作并没有使用到纯异步操作也没有使用配置,只因我们讲述的是最简单的原理,后面会逐渐构建起一个完整的框架。敬请期待!
源码下载:请点击
Aservicethatiscreatedbaseduponthearchitectureof
RESTiscalledasRESTservice.AlthoughRESTlooksmoreinclinedtowebandHTTPitsprinciplescanbeappliedtootherdistributedcommunicationsystemsalso.OneoftherealimplementationofRESTarchitectureistheWorldWideWeb(WWW).RESTbased
servicesareeasytocreateandcanbeconsumedfromawidevarietyofdevices.
REST(REpresentationalStateTransfer,表述性状态转移)。REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。
REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web服务,包括使用不同语言编写的客户端如何通过HTTP处理和传输资源状态。如果考虑使用它的Web服务的数量,REST近年来已经成为最主要的Web服务设计模式。事实上,REST对Web的影响非常大,由于其使用相当方便,已经普遍地取代了基于SOAP和WSDL的接口设计。
TherearemanyAPIsavailableindifferentlanguagestocreateandconsumeRESTservices.The
RESTitiseasytocreateaservicethatlooksRESTfulbuttheyareultimatelyanRPCstyleserviceoraSOAP-RESThybridservice.InthisarticlewearegoingtoseehowtocreateasimpleRESTserviceusingtheASP.NETWebAPI.
WebAPI来创建和使用REST服务。创建其他服务时很重要的是要遵循标准的协议(HTTP)。
在这篇文章我们来看看如何创建一个简单的
开发工具:VisualStudio2013
创建步骤:
1.模型化数据
创建一个新的ASP.NETWEB项目,在如下图界面选择Empty模板并且勾上WebAPI选项。(这里我们不使用Asp.netMvc4的方式去创建,我认为应该采用独立的方式去创建比较好)然后再Model中创建一个类Person:
1 2 3 4 5 6 7 8 9 10 11 | public class Person { public int Id{ get ; set ;} public string FirstName{ get ; set ;} public string LastName{ get ; set ;} } |
接着在Model中创建一个接口IPersonRepository
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public interface IPersonRepository { IEnumerable<Person>GetAll(); PersonGet( int id); PersonAdd(Personperson); void Remove( int id); bool Update(Personperson); } |
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 47 48 49 50 51 | public class PersonRepository:IPersonRepository { private List<Person>_people= new List<Person>(); private int num=1; public PersonRepository() { this .Add( new
"三" ,FirstName= "张" }); this .Add( new
"四" ,FirstName= "李" }); this .Add( new
"五" ,FirstName= "王" }); this .Add( new
"六" ,FirstName= "老" }); } public IEnumerable<Person>GetAll() { return _people; } public PersonGet( int id) { return _people.Find(p=>p.Id==id); } public PersonAdd(Personperson) { if (person== null ) throw new ArgumentNullException( "person" ); person.Id=num++; _people.Add(person); return person; } public void Remove( int id) { _people.RemoveAll(p=>p.Id==id); } public bool Update(Personperson) { if (person== null ) throw new ArgumentNullException( "person" ); int index=_people.FindIndex(p=>p.Id==person.Id); if (index==-1) return false ; _people.RemoveAt(index); _people.Add(person); return true ; } } |
2.使用ApiControllers访问API服务
UnlikeanASP.NET/MVCProject,whichgenerallyusesControllersderivedfromSystem.Web.MVC.Controller,aWebApiprojectwillgenerallyutilizecontrollersderivedfromSystem.Web.Http.WebApiController.LikethestandardMVCController,TheWebApiControlleracceptsincomingHTTPrequestsandprocessesaccordingly.However,thestandardMVCControllerreturnsaView,whiletheWebApicontrollerreturnsdata.
特别值得注意的是,WebApicontroller会检查接受HTTP请求头部。然后将NET对象序列化为适当的返回数据类型(XML或JSON)。
在Controllers文件夹上右键选择添加—>控制器,然后如下图选择
命名为PersonController。
现在您可以方便的在这里添加任何GURD代码。我们一起来分析一个具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | static readonly IPersonRepositorydatabasePlaceholder= new PersonRepository(); public PersonGetPersonByID( int
{ Personperson=databasePlaceholder.Get(id); if (person== null ) { //返回一个自定义HTTP状态码 throw new HttpResponseException(HttpStatusCode.NotFound); } return person; } |
如果没有找到相应id的联系人,则会抛出一个自定义HttpResponseMessage的异常,这个异常是指向的404异常,表示请求资源不存在。实际项目中,我们是非常有必要返回一些和操作对应的异常信息的。
完整代码如:
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 47 48 49 | public class PersonController:ApiController { static readonly IPersonRepositorydatabasePlaceholder= new PersonRepository(); public PersonGetPersonByID( int id) { Personperson=databasePlaceholder.Get(id); if (person== null ) { //返回一个自定义HTTP状态码 throw new HttpResponseException(HttpStatusCode.NotFound); } return person; } public IEnumerable<Person>GetAllPeople() { return databasePlaceholder.GetAll(); } public HttpResponseMessagePostPerson(Personperson) { person=databasePlaceholder.Add(person); var response= this .Request.CreateResponse<Person>(HttpStatusCode.Created,person); string uri=Url.Link( "Default" , new {id=person.Id}); response.Headers.Location= new Uri(uri); return response; } public bool PutPerson(Personperson) { if (!databasePlaceholder.Update(person)) { throw new HttpResponseException(HttpStatusCode.NotFound); } return true ; } public void DeletePerson( int id) { Personperson=databasePlaceholder.Get(id); if (person== null ) { throw new HttpResponseException(HttpStatusCode.NotFound); } databasePlaceholder.Remove(id); } } |
当然其中一个非常重要的WebAPI规范就是HTTP谓词的映射,如GET、POST、PUT、DELETE。那么正如我们上面所述,我们的动作也遵循了这个规范。原因是在ASP.NETWebAPI,一个controller是一个class(类)以处理HTTP请求(requests)。在controller里所有的公开方法(publicmethods)都称为Action方法或简称Action。当WebAPIFramework接收到一个请求,它路由请求到一个Action。
每个实体(entry)在路由表里都包含一个路由样板(routetemplate)。WebAPI的路由样板默认是"api/{controller}/{id}",此样板里,"api"是文字路径片段,{controller}和{id}是定位参数。
当WebAPIFramework接收到一个HTTP请求,它会去尝试比对URI对路由表的路由样板列表,如果没有符合的路由,Client会收到一个404错误。例如,以下URI会符合默认路由:
·/api/Person
·/api/Person/1
路由表定义如:
1 2 3 4 5 6 7 8 9 | config.Routes.MapHttpRoute( name: "Default" , routeTemplate: "api/{controller}/{id}" , defaults: new {id=RouteParameter.Optional} ); |
以下是一些可能HTTP请求及其含义:
HTTPMethod | URI路径 | Action | 参数 |
GET | /api/Person | GetAllPeople | 无 |
GET | /api/Person/1 | GetPersonByID | 1 |
DELETE | /api/Person/1 | DeletePerson | 1 |
POST | /api/Person | PostPerson | newPerson |
1 2 3 4 5 | config.Routes.MapHttpRoute( name: "Default" , routeTemplate: "api/{controller}/{action}/{id}" , defaults: new {id=RouteParameter.Optional} ); |
/api/person/GetPersonByID/1
也可以访问到需要的资源。
3.创建消费服务
根据项目的需要,你可以在你的API的客户端添加一个Person类。webapi懂得如何序列化和反序列化。NET类中的JSON或XML,都是使用中最常见的两种数据交换格式。Wecanre-writeourclientexamplestoutilizeaPersonclassifitsuitsourneeds,andpassinstancesofPersontoandfromourAPIprojectindirectlythroughserialization.Ourcoreclientmethods,re-written,looklikethis:
我们以控制台程序为例,新建一个控制台项目,假设命名为:RestApiClient
添加第一个类Person:
1 2 3 4 5 6 | public class Person { public int Id{ get ; set ;} public string FirstName{ get ; set ;} public string LastName{ get ; set ;} } |
然后新建一个类用来发送请求给WEBAPI,我们再次来分析这个类里面写些什么,列举一个方法:
1 2 3 4 5 6 7 | //发送一个HTTPGET请求给PersonControllerAPI: static JArraygetAllPeople() { HttpClientclient= new HttpClient(); HttpResponseMessageresponse=client.GetAsync( " ).Result; return response.Content.ReadAsAsync<JArray>().Result; } |
使用JSON前,需要引用Newtonsoft.Json的dll和usingNewtonsoft.Json.Linq的命名空间。LINQtoJSON主要使用到JObject,JArray,JProperty和JValue这四个对象,JObject用来生成一个JSON对象,简单来说就是生成"{}",JArray用来生成一个JSON数组,也就是"[]",JProperty用来生成一个JSON数据,格式为key/value的值,而JValue则直接生成一个JSON值。下面我们就用LINQtoJSON返回上面分页格式的数据。
下面就是定义一个HttpClient去发送一个GET请求给指定WEBAPI,然后利用HttpResponseMessage接收返回的JSON数据。
完整代码如:
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 | //发送一个HTTPGET请求给PersonControllerAPI: static JArraygetAllPeople() { HttpClientclient= new HttpClient(); HttpResponseMessageresponse=client.GetAsync( " ).Result; return response.Content.ReadAsAsync<JArray>().Result; } //发送一个带ID参数的HTTPGET请求给PersonControllerAPI static JObjectgetPerson( int id) { HttpClientclient= new HttpClient(); HttpResponseMessageresponse=client.GetAsync( " +id).Result; return response.Content.ReadAsAsync<JObject>().Result; } //发送一个匿名(类)对象HTTPPOST给PersonControllerAPI static JObjectAddPerson( string
string newFirstName) { //初始化一个匿名对象 var newPerson= new
HttpClientclient= new HttpClient(); client.BaseAddress= new Uri( " ); var response=client.PostAsJsonAsync( "api/person" ,newPerson).Result; return response.Content.ReadAsAsync<JObject>().Result; } static bool UpdatePerson( int personId, string newLastName, string newFirstName) { var newPerson= new
HttpClientclient= new HttpClient(); client.BaseAddress= new Uri( " ); var response=client.PutAsJsonAsync( "api/person/" ,newPerson).Result; return response.Content.ReadAsAsync< bool >().Result; } static void DeletePerson( int id) { HttpClientclient= new HttpClient(); client.BaseAddress= new Uri( " ); var relativeUri= "api/person/" +id.ToString(); var response=client.DeleteAsync(relativeUri).Result; client.Dispose(); } |
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 47 48 49 | Console.WriteLine( "TheProgramwillstart......" ); JArraypeople=getAllPeople(); foreach ( var person in people) { Console.WriteLine(person); } Console.WriteLine(Environment.NewLine+ "根据ID=2查询:" ); JObjectsinglePerson=getPerson(2); Console.WriteLine(singlePerson); Console.WriteLine(Environment.NewLine+ "添加一个新对象并返回" ); JObjectnewPerson=AddPerson( "曼迪" , "石" ); Console.WriteLine(newPerson); Console.WriteLine(Environment.NewLine+ "更新一个已经存在的对象并返回成功与否" ); JObjectpersonToUpdate=getPerson(2); string newLastName= "麻子" ; Console.WriteLine( "UpdateLastNameof" +personToUpdate+ "to" +newLastName); int id=personToUpdate.Value< int >( "Id" ); string FirstName=personToUpdate.Value< string >( "FirstName" ); string LastName=personToUpdate.Value< string >( "LastName" ); if (UpdatePerson(id,newLastName,FirstName)) { Console.WriteLine(Environment.NewLine+ "更新person:" ); Console.WriteLine(getPerson(id)); } Console.WriteLine(Environment.NewLine+ "删除ID为5的对象:" ); DeletePerson(5); Console.WriteLine( "输出所有对象" ); people=getAllPeople(); foreach ( var person in people) { Console.WriteLine(person); } Console.Read(); |
这里我偷了个懒,把他们写成一个部分类了,实际应该怎么写你懂得…
如果报每个方法最后一句出错,请加引用:"System.Net.Http.Formatting",可以在这里找到C:\ProgramFiles(x86)\MicrosoftASP.NET\ASP.NETMVC4\Assemblies\System.Net.Http.Formatting.dll真实的想法是实在不想加这个引用,原因请看下面。
另外遗憾的一点是我们对服务的消费操作并没有使用到纯异步操作也没有使用配置,只因我们讲述的是最简单的原理,后面会逐渐构建起一个完整的框架。敬请期待!
源码下载:
相关文章推荐
- ASP.NET Web API与Rest web api(一)
- 如何应用ASP.NET MVC中的分部视图
- Action Filters for ASP.NET MVC
- 【ASP.NET】——数据绑定和数据控件
- ASP.NET六大巨头——内置对象(2)
- 关于TagHelper的那些事情——Microsoft.AspNet.Mvc.TagHelpers介绍
- ASPxPopupControl PopupWindow使用方法
- aspectJ切面使用
- ASP.NET 5探险(5):利用AzureAD实现单点登录
- Metasploit 整理笔记
- 基于UML和ASP.NET实现三层B/S结构系统开发
- .net学习之ASPX页面属性
- Metasploit 学习笔记
- 在ASP.NET MVC5 及 Visual Studio 2013 中为Identity账户系统配置数据库链接及Code-First数据库迁移
- Asp.net Vnext api CORS( 跨域)
- ASP玩转微信公众平台自定义接口(1)—接口申请
- ASP.NET MVC图片管理(更新)
- ASP.NET - 无限极分类
- Spring学习(24)--- AOP之 Aspect instantiation models(aspect实例模式)特别说明
- Asp.net管道模型(管线模型)