当前位置: 亚洲城ca88 > ca88 > 正文

建立规范的ca88

时间:2019-09-22 02:39来源:ca88
本文所需的片段预备知识能够看这里: 本文所需的部分筹划知识能够看这里: 本文所需的片段图谋知识能够看这里: 本文介绍的是运用ASP.NET Core建构Richardson成熟度为2级的伪RESTful webAPI, 本

本文所需的片段预备知识能够看这里:

本文所需的部分筹划知识能够看这里:

本文所需的片段图谋知识能够看这里:

本文介绍的是运用ASP.NET Core建构Richardson成熟度为2级的伪RESTful web API, 本文介绍的是GET和POST.

创造Richardson成熟度2级的POST、GET、PUT、PATCH、DELETE的RESTful API请看这里:

创建Richardson成熟度2级的POST和 GET的RESTful API请看这里:

运用的品类是(右键另存为, 然后把后缀名改为zip):

本文将把WEB API项目初步进步到Richardson成熟度3级的冲天,就算一时还不曾兑现REST全数的封锁,不过曾经相比RESTful了。

事先一篇作品介绍了POST和GET,那篇要介绍建设构造Richardson成熟度2级的DELETE, PUT, PATCH.

RESTful API 财富 的命名指引职业

首先, 财富应该使用名词, 它是个东西, 不是动作.

例如:

  • api/getusers 便是不科学的.
  • GET api/users 正是不易的
  • GET api/users/{userId}.

之所以财富应该选拔的是名词.

万一是非分层结构的财富, 那么它不该这么命名: api/xxx/xxx/users, 而应该使用 api/users.

只假若单个财富, 不应有如此 api/id/users, 而应该是 api/users/{userId}.

(财富名是还是不是复数依然基于个人习于旧贯吗).

本文要求的代码(右键另存,后缀改为zip):

本文供给选拔的代码(右键另存,后缀改为zip):

取名应该可以反映能源的布局

例如 api/department/{departmentId}/emoloyees, 那就代表了department 和 职员和工人从前是主题关系.

api/department/{departmentId}/emoloyees/{employeeId}, 就表示了该机构下的某部职员和工人.

而过滤, 排序等不是能源, 所以那样写 api/users/orderby/username 是不得法的.

过滤排序那类的参数是足以看做查询参数字传送递进来的, 正确的写法应该是: api/users?orderby=username.

可是有时, RPC风格的办法调用很难映射成规范的能源命名, 所以不时能够打破行业内部 举例 api/users/{userId}/totalsalaries.

HATEOAS(Hypermedia as the engine of application state)是 REST 框架结构风格中最复杂的束缚,也是营形成熟 REST 服务的着力。它的第一在于打破了顾客端和服务器之间严酷的合同,使得顾客端能够越发智能和自适应,而 REST 服务本人的演化和翻新也变得进一步便于。

DELETE 删除财富

以此很简短,以删除City为例:

ca88 1

先是查找Country,没找到就回来404 Not Found;然后搜索City,没找到也回到 404 Not Found;假若找到了,删除保存的时候退步,则赶回 500 Internal Server Error;如若剔除成功,则无需回到什么内容,重回204 No Content就能够。

测试:

ca88 2

倘诺重复实行该乞求的话,不出意外的会重临 404 Not Found:

ca88 3

DELETE并不富有安全性,因为在艺术施行后会改动财富。

但是DELETE是颇具幂等性的,那些您或然会有疑点,小编推行数十次DELETE后赶回的状态码不相同样为啥还装有幂等性。

事先小编提过幂等性的粗略定义,这些定义多少有一点模糊,我们再来看一下幂等性定义里第一的一句话:“the side-effects of N > 0 identical requests is the same as for a single request”,意思是反复须要的副作用和单次乞求的副效率是均等的。幂等性的为主概念能够知晓为:"你能够发送多于二遍的一样供给,不过不会对服务器变成额外的改换"。也等于说每便发送了DELETE央求之后,服务器的景观都是同等的

应该利用什么类型作为ID

一经利用int型作为ID的话, 超过58%时候是绝非难点的, 可是只要你使用的数据库的ID是自增整型的, 要是你替换数据库了, 然后把原本数据迁移到新数据库了, 那么现成数量的ID就会发生变化, 那么一定于全体的能源的地址产生了扭转, 那就违背了这么些:

财富的U奥迪Q5I应该永久没什么差异的.

据此GUID应该作为ID来选用. (不过本身为着便利, 照旧接纳自增int作为ID吧).

应用GUID作为主键的补益就是:

  • 能够切换数据库
  • 自然层度上隐敝了中间贯彻细节

HATEOAS的帮助和益处有:

一路删除主从财富

这种情景也很普及,在剔除Country财富的还要,把它的子财富City也删掉。

ca88 4

那么些很简短,由于EFCore做了数不尽办事,就不需求在剔除主能源的时候手动去删除它富有的子财富了。

测试:

ca88 5

经过HTTP方法与能源互相

针对项目里的Country这么些能源, 请参谋上面这几个列表:

ca88 6

此处GET能够领略为获取能源, POST为丰裕能源, PUT为完全立异能源, PATCH为一些更新财富, DELETE为除去能源.

此处供给提的是后五个:

  • HEAD: 和GET大概, 不过它不该回到响应的body, 全体未有响应的payload. 它最首要行使来收获财富的一些消息, 举例查看能源是不是可用等.
  • OPTIONS: 它是用来查询某些能源UTiguanI的可交互情势有怎么着, 换句话说便是, 使用它能够明白有个别UPRADOI是或不是能够施行GET或然POST动作, 这几个结果经常是在响应的Headers里面而不是body里, 所以也未有响应的payload.

具备可进化性何况能本人描述

删除集独财富

DELETE "

建立Controller

首先供给创立二个CountryController:

ca88 7

在意在CountryController上边标记的[Route]性情标签,它的值是一切Controller下全数的Action的路由前缀,能够写成固定的地点,也足以写成"api/[controller]", 其中[controller]那部分会造成那些Controller的名字,这里也正是"api/country".

只要选拔[controller]的话,借使Controller重构后名字改了,那么该Controller的路由地址也便是能源的地址也就改了,那样相当不好,所以提出依然写成固定的地点不要使用[controller]。

超媒体(Hypermedia, 比方超链接)驱动怎么着花费和选取API, 它报告客商端怎么着采纳API, 如何与API交互, 例如: 如何删除财富, 更新能源, 创造能源, 怎么样访问下一页能源等等.

PUT 更新能源

Put应该用来对财富的总体立异

出于PUT是对能源的完整修改,须要body中应当带着立异目的,所以先创制这几个目的:

ca88 8

我City那几个Model就唯有四个字段,而id的相应作为路由的参数字传送递进来,所以在CityUpdateResource里面就无需id属性了;固然有Id的话,你大概还要与路由参数里的id进行比较,假若差异会带来麻烦,所以那些指标里不带id。

这儿你也足以窥见CityUpdateResource和CityAddResource所富含的属性是一样的,那么为何不应用同三个体系呢?因为那七个目的的目标差别,权利差别,贰个类只应该有多个专门肩负。然则你能够使用有个别父类把同样的本性抽取出去,然后分别承继,不过自身就不那样做了。

上边看这些PUT的Action方法:

ca88 9

其一办法也很轻松,当中有两点须要潜心:怎么把传递进入的指标的持有属性值都传送给EFCore的Model?这里运用AutoMapper就可以,上面红框的办法便是把第三个参数对象的性质映射到第二个参数对象上。

再有正是理所应当回到什么?小编以为Ok和NoContent都是足以的,借使在Action的法子里有个别质量的值是在这里改变的,那么能够应用Ok把最新的对象传递回去;不过如果在Action方法里不曾再修改其余性质的值,也等于说更新之后和传递步入的对象的属性值是一样的,那就不曾必要再把最新的指标传递回去了,那时就应当运用NoContent。

再看一下Repository里面:

ca88 10

瞩目这几个是DbContext的诀要并不是DbSet的法门,它会跟踪city,然后把它的ModelState设置为Modified。

测试:

ca88 11

OK.

上面做另八个测量试验,假诺body里面包车型地铁对象缺少有个别性能呢?(由于目的自己独有壹本性格,作者就传递三个无属性对象啊- -!):

ca88 12

操作结果依然是没问题的,使用GET反查一下:

ca88 13

name属性就成为了null,这简单领会,PUT是全部性更新,假诺传递的参数对象缺乏有些品质,那么这一个属性的值就一定于是null,也会完全立异给Model。

是因为这种原因,PUT用的就相当少,不容许为了革新指标中的叁个性格而把指标具有的属性值都传送回去。

为此PATCH就使用的可比宽泛了。

PUT不富有安全性,因为老是实践PUT都会转移能源。

但是PUT具备等幂性,这么些很好理解,数十次实行同一个PUT央浼后,结果是均等的。

GET 资源

GET 所有的Country:

ca88 14

AutoMapper的运用办法这里就不介绍了

GET 一个Country:

ca88 15

那多少个格局里重临的都是JsonResult,那看起来没什么难点,因为我们想要的正是JSON格式的结果。以第2个办法为例,使用POSTMAN测验,借使能查询到数量:

ca88 16

那是没万分的,不过只要查询多少个不设有的财富:

ca88 17

那就格外了,倘诺查询不到能源,那么再次来到的相应是404 NOF FOUND 并非200 OK.

诸如上边便是三个不使用HATEOAS的响应例子:

立异集合能源

跟删除集结财富同样,针对有个别路由进行联谊恳求是官方的,不过那也意味着传进来的成团要完全代替本来的集纳,也正是说原有集合里面包车型地铁指标都应当删除,然后传进来集合的靶子挨个再增加进去。但是那样的话是有副作用的,每一次实施的结果其实是不相同的。别的这种群集更新也是怀有异常的大的破坏性,所以一般不那样做。

状态码

意况码是特别关键的,因为唯有状态码会告诉API的顾客:

  • 呼吁是还是不是如预期的功成名就,只怕退步
  • 要是出现了不当,什么人该为那几个张冠李戴承担

上边再列举一下web API会用到的状态码:

200等第,表示成功:

  • 200 - OK
  • 201 - Created,表示能源创设成功了
  • 204 - No content,成功进行,不过不应当回到任何事物

400等级,表示客户端引起的荒唐:

  • 400 - Bad request,表示API的买主发送到服务器的呼吁是破绽非常多的
  • 401 - Unauthorized,表示不曾权限
  • 403 - Forbidden,表示客户验证成功,可是该客户依旧不大概访谈该能源
  • 404 - Not found,表示须要的财富不设有
  • 405 - Method not allowed,那便是当咱们尝试发送央浼给有些财富时,使用的HTTP方法却是差别意的,比如利用POST api/countries, 而该能源只兑现了 GET,所以POST不被允许
  • 406 - Not acceptable,这里涉及到了media type,比方API花费者央求的是application/xml格式的media type,而API只援助application/json
  • 409 - Conflict,表示该央求不能够实现,因为央求与日前财富的处境有抵触,比方你编辑某些能源数量之后,该能源又被另旁人立异了,那时你再PUT你的数目就能够现出409不当;不经常也用在品味创设能源时该能源已存在的动静。
  • 415 - Unsupported media type,那一个和406恰好回去来,比如说作者向服务器交由数据的media type是xml的,而服务器只援救json,那么就能回来415
  • 422 - Unprocessable entity,表示乞请的格式没难题,不过语义有不当,比如实体验证错误。

500品级,服务器错误:

  • 500 - Internal server error,这象征是服务器产生了不当

归来刚才的那七个措施,暗许情况下 JsonResult会再次回到200 OK状态码,能够去修改JsonResult以支撑任何的状态码。不过Controller里提供了一些声援方法再次来到IActionResult并点名特定的状态码,针对200,便是Ok()方法。

ca88 18

这时就无需手动重回JsonResult了。

那边必要留意的是,针对集结的剧情协商,设若群集是空的,也不该回到404,因为这一个Country财富是存在的,只可是它的剧情是空的而已。

接下来看一下GET 特定单个能源:

ca88 19

针对单个能源,若无找到,就须要回到404 Not Found,那时就能够运用Controller的支持方法 NotFound().

ca88 20

{    "id" : 1,    "body" : "My first blog post",    "postdate" : "2015-05-30T21:41:12.650Z"}

履新或创制财富

笔者记得好像在利用老版本Entity Framework做种子数据的时候,常常接纳一个恢弘方法叫做AddOrUpdate(),也便是若是数量存在那就革新它,不然就创制它。

在REST API里,大家一时候也会境遇那样的要求。我们一时把那个点子叫做Upsert (Update Insert) 。那么难题来了应该使用POST依旧PUT呢?

PUT央求会发送到现成资源的URAV4I上,要是财富子虚乌有就回来404。

而POST用于制造能源,所以必然不知道该财富的ULacrosseI(是指GET的UEvoqueI)。

可是只要API的主顾能够创设能源,那么,PUT伏乞能够被发送到七个不经常不真实的能源的UOdysseyI上;倘若能源不设有,那就成立它,不然就修改它。

因而倍感使用PUT作为Upsert的HTTP方法比较适合一些。

可是只要接纳自增类主键Id的话,这种状态就不切合了。

下边大家如若City的Id不是自增的,那么大家得以这么修改一下Update方法:

ca88 21

出于小编的例证主键是自增的,所以不相符Upsert。作者就不测量试验了。

可是完全的思路正是那般,注意里面新增添和修改重临的结果略有差异。

拍卖极度

当Action爆发极度的时候,默许情形下ASP.NET Core会重临500:

ca88 22

ca88 23

但依然友好管理一下相比好,能够在Action里面使用try catch:

ca88 24

此处由于是服务器的失实,所以应当回到500场合码 Internal Server Error。

只顾这里不应有重回Exception,因为那是程序的中间贯彻细节,再说它对顾客来讲也没怎么用。

ca88 25

别的,大家还足以全局管理特别。

在Startup里面的Configure方法:

ca88 26

使用app.UseExceptionHandler(),里面能够自定义一些逻辑。假设那地方代码比非常多以来,能够把它封装成八个恢宏方法,然后使用app.Usexxx的样式调用。

回头小编把Action里面包车型大巴try catch去掉试试,可是此间要专一把条件变量ASPNETCORE_ENVIRONMENT的值改成Production(其实不是Development就能够):

ca88 27

如果不选择HATEOAS的话, 恐怕会有那个主题材料:

PATCH 局地更新财富

利用PUT最完全立异,劣势依然很鲜明的,所以自身越来越多利用的是PATCH局地更新。

HTTP PATCH须求的body部分必要运用RFC 6902 (JSOn Patch)其一专门的学问来开展描述。

而PATCH央求的media type应该设定为 "application/json-patch json"。

PATCH请求的body是一个操作的数组

ca88 28

本条例子里面有八个操作:

率先个是“replace”操作(op的值便是操作的品种),path代表着财富的属性名value代表的是立异后的值

其次个操作类型是“remove”,表示要去除财富的有些属性的值,例子里是name属性。

JSON PATCH的操作类型重要有三种:

  • 添加:{“op”: "add", "path": "/xxx", "value": "xxx"},如若该属性不存,那么就增多该属性,假若属性存在,就改造属性的值。那么些对静态类型不适用。
  • 删除:{“op”: "remove", "path": "/xxx"},删除某些属性,或把它设为暗许值。
  • 替换:{“op”: "replace", "path": "/xxx", "value": "xxx"},改造属性的值,也得以知晓为先实行了删除,然后进行加多。
  • 复制:{“op”: "copy", "from": "/xxx", "path": "/yyy"},把某部属性的值赋给目的属性。
  • 移动:{“op”: "move", "from": "/xxx", "path": "/yyy"},把源属性的值赋值给指标属性,并把源属性删除或设成暗中认可值。
  • 测试:{“op”: "test", "path": "/xxx", "value": "xxx"},测量检验指标属性的值和点名的值是大同小异的。

只顾,path属性只怕全数层级结构,而value属性也不用非得是字符串。

看下代码:

ca88 29

传送步向的body参数需求动用JsonPatchDocument<T>本条类型,在此处自个儿把它称作patchDoc。首先要把EFCore的City映射成CityUpdateResource,那样那一个CityUpdateResource就有了该City在数据Curry流行的属性值。然后通过patchDoc.ApplyTo()那些措施把patchDoc的操作依次外加给那几个CityUpdateResource,那时候全部必要立异的值都反映在CityUpdateResource里了,而该对象别的的属性值则是数据Curry的摩登值,也正是没有必要更新的值。最后再把它的值映射给EFCore的City,进行创新就足以了。最终EFCore做的操作必然是欧洲经济共同体制革新进,不过在此之前大家把最新值都投身CityUpdateResource里了,所以就一定于只做了一部分更新。

测试:

请求的Content-Type应该是"application/json-patch json",可是若是之写成application/json好像也得以。

ca88 30

结果:

ca88 31

(为了更好的测验,小编又为City增添了Description属性)

下面remove的测试:

ca88 32

反查:

ca88 33

在测量试验一下多个操作:

ca88 34

结果就不看了,都以OK的。

GET 父亲和儿子关系的能源

那是三个头名的光景,二个国家包罗四个都市,这正是老爹和儿子关系。

先是看一下domain model:

ca88 35

ca88 36

其一理应很简短。

别的还要创设CityResource,Repository和IRepository,注册配置,种子数据等等,那几个就不贴了。

上面创设CityController

ca88 37

前面提到过,针对老爹和儿子、主从关系的能源,其子能源的路由地址应该是地点那样的,由于该Controller下全体的Action的路由前缀都以同一的,所以把那些路由放到了Controller等级作为持有Action的前缀。

而GET方法自己相比较轻便,没什么说的,里面涉及的局地主意请自行编排。

探访运营结果:

ca88 38

借使找不到Country,则赶回404:

ca88 39

下面GET 单个city:

ca88 40

小心,单个能源找不到就应有回到404,而空集合怎不是,这一个前边也提过。

找到能源的结果:

ca88 41

找不到country或许city的时候都应当回到404,就不贴图了。

  • 顾客端越来越多的急需理解API内在逻辑
  • 如果API产生了某个变动(增多了附加的条条框框, 改动法规)都会损坏API的成本者.
  • API不能够单独于开支它的运用实行进化.

PATCH用来一些更新或创立财富

能够修改相关代码来援助部分更新或创设能源的操作:

ca88 42

其一小编就不测量检验了,自增Id不符合这种操作。

内容协商

一句话来说来讲就是,假诺财富支撑各种表现格式,那么花费者能够挑选它想要的格式

此间将在选拔media type,它能够通过须要的Accept Header来传递,常见的有:

application/json 和application/xml...等等

在尚未钦赐Accept Header的状态下,就该重临一个暗许的格式,在ASP.NET Core 2.0里面纵使application/json。

当呼吁的media type不可用的时候,何况花费者不扶助默许格式,这时服务器就活该回到 406 Not Acceptable 状态码。

ASP.NET Core 扶助出口和输入三种格式化器

出口的media type在accept header里面,而输入的media type在content-type header里面

看一下当下的状态,要求的Accept Header为application/json时:

ca88 43

请求的Accept Header为application/xml时:

ca88 44

它们再次回到的都以json格式的。

因为服务器今后不帮忙xml,所以回来了暗中同意的json格式,但严峻来说,那样做不科学,所以需求处理一下。

在Startup里,ConfigureServices方法:

ca88 45

把这个ReturnHttpNotAcceptable属性设为true,假诺想要的格式不援助,那么就能回去406 Not Acceptable:

ca88 46

不钦赐Accept Header的状态下就回去暗中同意的json格式:

ca88 47

下边,为品种增多Xml输出格式的帮助:

ca88 48

再试试:

ca88 49

那时就成功的归来了xml。

即使利用HATEOAS:

HTTP方法适用总计

常用的5中HTTP方法都介绍了,上面总括一下:

GET:

  • GET api/countries,重临200,集结数据;找不到数码再次来到 404。
  • GET api/countries/{id}, 再次来到200,单个数据;找不到重临 404.

DELETE

  • DELETE api/countries/{id},成功204;没找到能源 404。
  • DELETE api/countries,很少用,也是204或者404.

POST :

  • POST api/countries, 成功重临 201 和单个数据;假若能源没有开创则赶回 404
  • POST api/countries/{id},肯定不会成功,重临 404或409.
  • POST api/countrycollections,成功重回 201 和聚焦;没创设财富则赶回 404

PUT :

  • PUT api/countries/{id}, 成功足以回来200,204;没找到能源则赶回 404
  • PUT api/countries,集结操作相当少见,重临 200,204或404

PATCH:

  • PATCH api/countries/{id},200单个数据,204照旧404
  • PATCH api/countries, 集结操作相当少见,重回 200汇合,204或404.

创设资源

第一掌握一下措施的安全性和幂等性。

安全性是指方法实行后并不会更改能源的表明。

幂等性是指方法无论奉行多少次都会获得一致的结果。

上边是HTTP方法的安全性和幂等性列表:

ca88 50

参照他事他说加以考察这么些列表能够扶助调整在某种景况下用哪一类HTTP方法。

下边看看创造Country的代码:

ca88 51

以此代码很简短,数据是从乞请的body带进来的。

内需留意的是回去什么,假设POST操作施行成功的话,标准的做法是返回201 Created 状态码。

在此间就足以行使CreatedAtRoute() 那个格局,它同意响应里带着Location Header,在那几个Location Header里包括着叁个uri,通过那么些uri就能够GET到大家正好创制好的能源。

本条格局的首先个参数是三个路由名,使用那几个路由名能够用来变化刚才提到的uri。在本例里,那么些路由名应当相应的是GetCountry这么些Action方法,所认为这几个Action增多路由名:

ca88 52

如此就和Post方法再次回到中用到的路由名同样了,第二个参数是多少个佚名类里面有个特性id,它会编制程序路由里的参数,最终二个参数是响应会再次回到的数码。

上边进行测量检验,发送乞请的时候别忘了设置Content-type为applicaiton/json:

ca88 53

然后是多少:

ca88 54

接下来发送央求,查看响应的body部分:

ca88 55

再看响应的header:

ca88 56

这里能够见到Location Header的uri,通过那些uri,你就足以GET到那些刚刚创制的Country财富,这里自身就不测验了。

假若重复执行那个POST操作,看看结果:

ca88 57

这一次回去的数额的id为6,与前边不等同,所以POST不是幂等的,它每便实践后的结果是分裂等的。

{    "id" : 1,    "body" : "My first blog post",    "postdate" : "2015-05-30T21:41:12.650Z",    "links" : [        {            "rel" : "self",            "href" : http://blog.example.com/posts/{id},            "method" : "GET"        },
     {
        "rel": "update-blog",
       "href": http://blog.example.com/posts/{id},
        "method" "PUT"
        }
        ....    ] }

验证

为了实行输入验证,大家须求做以下三方面工作:

  • 概念表明准绳
  • 检查验实准则
  • 把验证错误音讯发送给API的费用者

此前的稿子也关系的ASP.NET Core里面定义表明准绳的不二诀要:

  • Data annotations 数据评释,正是这种在品质上边的中括号样式的属性标签
  • 怎么着数据注解不恐怕满意要求,则足以应用自定义的证实措施
    • 能够自定义数据表明
    • 也足以让被验证类达成IValidatableObject接口
  • 也得以选择像FluentApi那样的第三方验证库

反省验证法则的点子:

  • 使用 ModelState
    • 它是二个字典,包罗了Model的场所以及Model所绑定的辨证
    • 对此提交的各种属性,它都富含了三个错误消息的集纳
  • ModelState.IsValid(),如若出现其余八个荒唐,ModelState.IsValid属性就能够化为false。

告知证实错误音信:

  • 回到的状态呢应该是 422 Unprocessable Entity (上文讲过,422象征伏乞的格式没难题,不过语义有不当,比如实体验证错误)
  • 除了那几个之外状态码之外,还索要把注明错误音信在响应的body里面带回去

成立子能源

Country的创建做完了,今后可以成立City了。

ca88 58

以此跟上面包车型客车大半,只可是注意须要弹指间路由的参数就可以。

测试:

ca88 59

本条response里面包蕴了若干link, 第三个link包蕴着获得当前响应的链接, 首个link则告知顾客端怎样去创新该post.

为EFCore的Model加多约束

本身前边还向来不为EFCore的model加多约束,这里本身增多上(由于自个儿动用的是内部存款和储蓄器数据库,所以上边包车型大巴牢笼是不起成效的,那一个约束唯有在关系型数据库才起成效):

ca88 60

ca88 61

对于EFCore的实体约束和认证,小编不乐意利用评释的法子(因为Model类应该只干自个儿的活),更爱好使用fluent api

接下来把那八个类增多到DbContext里面包车型大巴OnModelCreating方法里就可以:

ca88 62

就算如此上面包车型客车代码对内部存款和储蓄器数据库未有用,可是自个儿也许增添上吧。

假使贰个HTTP要求形成了EFCore model的辨证战败,假使回去500的话,认为就不太精确。因为只借使500不当的话,就意味着是服务器现身了错误,而那件事实上是API花费者提交的数量非常,是客商端的失实。所以回到的状态码应该是 4xx 系列。

其余,近年来那几个验证法则是地处EFCore 的实体上的,而告诉给API花费者的印证错误新闻应该定义在Resource这一层表面,所以下边就为Resource model定义说明准则:

ca88 63

ca88 64

不无的注脚申明能够查看官方文书档案:

(这种方法比较简单,然而把验证和Model混合到了一块儿,所以重重人照旧不采用这种措施的)

表明准则定义完了,上边来实行准则检查。那时就需要动用ModelState了。

每当要求步入到这一个艺术的时候,都会表明大家刚刚定义在Resource上的这几个约束,借使内部叁个封锁未有达到规定的规范,则ModelState的IsValid属性就能是false;另外借使传进来的习性类型和定义的不合,IsValid属性也会是false。

此处重返状态码 422 是准确的选拔,然而 422 要求央求的body的语法必须是不利的,不可能是null,所以前边防检查查是或不是为null的代码还亟需保留。

鉴于ASP.NET Core并未放置的帮忙方法能够回去422和表达错误新闻,所以我们先创设二个类用于再次来到422 和认证错误音讯,它继续于ObjectResult

ca88 65

其中的SerializableError概念了一个方可被串行化的容器,该容器能够以Key-Value对的格局来保存ModelState的新闻。

回到CityController的POST的Action方法,只增多那部分代码就可以:

ca88 66

下边进行测量试验:

ca88 67

能够见到验证的错误信息都按预期重回了。

再试试其它一组测量试验:

ca88 68

下边思考下一旦据注脚不可能满足验证须求的情景,那时就要求写自定义的注脚。

前面小说讲过,有三种方法能够写自定义表明逻辑:

  • 自定义表明属性标签,编写贰个后续于ValidationAttribute的类
  • 让Resource类实现IValidatableObject接口
  • 利用FluentValidation以及近似的第三方库
  • 直白在方式里写验证逻辑

自身很赞成于后三种办法,尤其是第两种。不过出于本文首纵然讲RESTful API相关的,所以自身先制止过多的利用第三方库,笔者一时半刻先接纳第八种情势。

即使小编需要City的name属性值不得以是“中华夏族民共和国”:

ca88 69

此地要用到ModelState的AddModelError方法。

测试:

ca88 70

OK.

上面看一下PUT的表达。

绝大大多意况下,PUT的注解大概和POST是一律的,可是有的时候仍旧不雷同的,所以个别写多个ResourceModel对应POST和PUT的优势就体现出来了。

不过那些类的超越二分之一代码仍然一直以来的,所以能够使用利用抽象父类的不二诀要来去掉重复的代码,组建CityResource:

ca88 71

留心属性须要求动用virtual关键字,因为在子类里大家或然会重写属性。

在这里本身把Description的Required约束去掉了。

再看CityAddResource:

ca88 72

承袭抽象类就能够,属性和认证完全等同。

再看CityUpdateResource:

ca88 73

那边,小编对Description属性增多了Required约束,而任何约束和父类保持一致。

末了修改PUT的Action方法:

ca88 74

测试,POST:

ca88 75

OK。

再测试PUT,尤其是Description属性:

ca88 76

子类里Description的羁绊举行了检讨。

再测验父类里Description的封锁:

ca88 77

OK, 表明子类里Description的束缚和父类里Description的束缚都起效能。

在子类CityUpdateResource里,还是能这么写:

ca88 78

那样恐怕更清晰。

到近年来停止,笔者使用的是数码评释的格局来为ResourceModel增多求证准绳,那样做并不是很好,没有关心点分离(Soc,Seperation of Concerns)

并且,大家的自定义验证代码也是大街小巷重复的写,那样也不对。

由此就算数据注脚看起来很轻易,少写了部分代码,不过开拓软件应该特别尊重可维护性,要尽也许听从那么些设计规范,适当使用设计格局,写单元测量试验和E2E测验,就算这样会变成看起来多写了一些代码,不过思索到软件的质量以及更主要的末日维护,实际上那样做是大大的节省了资本。综上原因,作者引入应用第三方库,FluentValidation

并且创设父亲和儿子能源

那是个常见的急需,三个Country和它下属的Cities同期被传送进入,然后在Action里一同创设。

先是必要修改CountryAddResource:

ca88 79

接下来,就从未有过然后了,全部的炫丽操作都交由AutoMapper和EntityFramework Core了。。

测试:

ca88 80

然后GET这两个Cities:

ca88 81

罗伊 Fielding的一句名言: "一经在安顿的时候顾客端把它们的控件都置于到了设计中, 那么它们就不能够获得可进化性, 控件必需能够实时的被发现. 那正是超媒体能完毕的."

使用FluentValidation

安装FluentValidation,能够通过Nuget,Package Manager Console 或然 .net cli:

直白设置那么些就足以:

ca88 82

然后会自行安装注重的库:

ca88 83

把那二个ResourceModel的数量注解验证约束都去掉,把Controller里面自定义表达的代码也去掉,然后为每三个类增添多少个验证器Validator:

率先是Country的,那几个轻便:

ca88 84

个中山高校括号里面包车型地铁字符串是参数,{PropertyName}就算属性的名字要是应用了WithName()措施,那正是WithName里面设定的别称;{MaxLength}正是指设定的最大尺寸约束的值。有过多这种占位符,照旧必要看官方文书档案。

上面看看City相关的证实,这里有个持续的关系,首先是把共有的验证提抽取来作为父类:

ca88 85

此处运用泛型相比较好。

然后CityUpdateResource:

ca88 86

是因为父亲和儿子关系,父类的构造函数先进行,然后实践CityUpdateResourceValidator的构造函数。

最后还要为ASP.NET Core配置FluentValidation,在Startup的ConfigureServices方法里:

ca88 87

第一利用增加方法AddFluentValidation();然后为每叁个Resource Model 配置验证器。假若您不想挨个增多配置验证器的话,能够利用:

ca88 88

来把某部Assembly里的验证器全部丰富进去,不过本人大概比较欣赏三个贰个写,重构的时候有哪些错误能立刻开掘,可是也便于忘记增添。

然后测量试验一下,效果和事先是一模二样的。

使用FluentValidation,做到了很好的握别,作者个人感觉相当好,纵然多写了些代码,但是更加灵活,也更易于维护。

创设集独财富

这一次小编要三次性拉长三个会晤的Countries。

出于Country的集纳也正是是别的一种财富,所以可以把它放到单独的Controller里面,不放也没难题。

ca88 89

这么些其实也没怎么特别的,注意传进来的参数是IEnumerable。为了便于,权且先回去OK()。

测试:

ca88 90

OK, 下边化解再次来到的难点.

小编们要回去的是CreatedAtRoute方法, 由于内部要含有能够回到该集合财富的路由地址, 所以要求成立三个Action, 它的参数应该是POST方法重返数据的Id的集结. 不过出于路由参数不协理集结情势, 只好以字符串格局传递, 所以能够做成那样的路由参数: api/xx/(1,2,3,4,5).

而Action方法呢, 接受的参数应该是Id的汇聚, 应该是三个汇集类型, 所以大家得以选择ModelBinder把id字符串转化为id的集合:

ca88 91

接下来, 还索要相应这一个POST Action 做贰个GET会集的Action 方法:

ca88 92

本条Action所企望的参数类型是Id的汇聚, 而实际传入的是id的字符串, 通过ArrayModelBinder来达成转化.

谈到底修改POST方法的回来:

ca88 93

测验一下:

ca88 94

接下来再GET那么些链接:

ca88 95

OK

本着地点的例证, 作者可以在不改动响应中央结果的意况下增进别的多少个去除的法力, 客商端通过响应里的links就可以意识那么些删除功效, 可是对任何一些都没有影响.

PATCH的验证

PATCH与POST和PUT的表明稍微有几许两样,首先看三个事例,删除贰个不设有的性质的值:

ca88 96

那么些会导致再次来到500不当,那是畸形的。

此刻,可已利用patchDoc.ApplyTo的二个重载方法,它尚可ModelState作为参数,所以patchDoc里面有任何表明错误都会在ModelState里面显示出来,(注意是PatchDoc的印证错误并不是CityUpdateResource)

ca88 97

然后重新测量检验:

ca88 98

自家从前早就设定了CityUpdateResource的Description属性是必填的,那本人再做三个PATCH测量试验,把该属性的值去掉:

ca88 99

它回到了 204, 也正是说被成功的进行了,那么早晚是不怎么地点并未做约束检查遗漏了。

因为我们只检查了patchDoc,而从不检查手动构造建设的不得了CityUpdateResource(cityToPatch),所以那边可已选用TryValidateModel,来手动物检疫查cityTo帕特ch:

ca88 100

测试:

ca88 101

这次OK了。

只要POST到单个能源的地方

假诺POST到这么些地点 ,

那么, 借使该id的财富海市蜃楼, 则应该回到404;

假定该id的财富存在, 则应该回到409 Conflict.

(POST不是幂等性的, 它不可能多次央求都爆发同样的结果).

测验一下id的财富不设有的情状:

ca88 102

在测量试验一下Id的能源存在的情景:

ca88 103

依旧404, 那个充裕, 所以要求手动管理:

ca88 104

拜见结果:

ca88 105

OK, 无论是Id存在的能源依旧不设有的财富都会再次来到正确的景况码.

HTTP公约如故很匡助HATEOAS的:

Log

在筹划知识小说里,笔者一度介绍了Log相关的剧情,所以这边就不再重复陈述了(

看大家前边写的抓获万分的代码,在Startup的Configure方法里:

ca88 106

近日的代码是为API的主顾重回了500状态码,并回到了有个别错误音信。那样做我们就把十二分音讯给扬弃了,可是又不应有把非常音信传送给API开支者,而笔者辈实在供给那么些特别消息,所以我们把那多少个记录到日志。

有各类艺术能够得到Logger,这里小编动用ILoggerFactory:

ca88 107

然后在Configure方法里面相应的地方创设Logger并记下日志:

ca88 108

一切应用的日记还是做分类相比好,这里笔者利用LoggerFactory的CreateLogger方法成立了Logger,其分类是“Global Exception Logger”。

此处运用了500当做Log的伊芙ntId相比适合,毕竟是500不当。

本身认为能够把Action里面重返500状态码的有的改成抛出十三分。

然后自身修改一下PATCH,以便能抛出八个丰硕:

ca88 109

测试:

ca88 110

分外被平常的抛出,在看一下调整台的Log:

ca88 111

Log音讯也被科学的打字与印刷。

上边在拜见怎么着在Controller里面记录日志,首先注入Logger:

ca88 112

ILogger<T>,T正是日记分类的名字,这里提出使用Controller的名字。

接下来在Action里健康记录日志就能够了:

ca88 113

就不测验了。

支撑输入任何系列的Content-Type

事先讲过怎么样回到xml的格式, 上面介绍一下怎么采纳xml格式举办呼吁, 首先在Startup.cs里面增多那一个:

ca88 114

然后, 必要把供给的Content-Type设为application/xml:

ca88 115

自身就不适用xml数据开展测量检验了.

这一次先到这, 随后会写DELETE, UPDATE, PATCH.

本文的源码地址:

ca88 116

若果你细心想转手, 那就是我们一向浏览网页的格局. 浏览网址的时候, 大家并不关怀网页里面包车型大巴超链接地址是或不是变动了, 只要明白超链接是为啥就能够.

使用Serilog

在实质上接纳中只把日记记录到调整台或Debug窗口是没用的,最棒的方法仍然记录到文件只怕数据库等。

帮忙ASP.NET Core的第三方Log提供商有比比较多,NLog,Serilog等等。这里自身利用Serilog(

Nuget安装:

ca88 117

唤醒安装的重视:

ca88 118

然后在Program.cs里使用扩充方法UseSerilog()行使Serilog就能够,小编就不做别的配置了:

ca88 119

Serilog辅助把日志写入到各样的Sinks里,能够把sink看做媒介。

自己要求写入到文件,那么就设置:

ca88 120

Serilog的配置新闻是那样写的,能够把它放到程序比较靠前执行的地点:

ca88 121

这边配置的乐趣是:全局最低记录日志等级是Debug,可是本着以Microsoft开始的命名空间的最低端别是Information。

应用Enruch.FromLogContext()能够让程序在实践上下文时动态增进或移除属性。

按日生成记录文件,日志文件名后会带着日期,并放到./logs目录下。

那便是变化的日记文件:

ca88 122

小心使用了其余Log提供商之后,在它此前安顿的Log提供商就不起成效了,所以调控台不出口Log的老大新闻了:

ca88 123

从而依旧为Serilog增添三个调控台的Sink吧:

ca88 124

ca88 125

如此调控台和文书的Log都能够出口了:(注意windows下的指令行临时候会堵塞,供给按一下回车工夫承继)

ca88 126

此次就写到这里,后一次写一些翻页和过滤的事物。

完了后的源码:

咱俩得以点击超链接实行跳转, 也得以提交表单, 那就是超媒体驱动应用程序状态的例子.

假定服务器决定改动超链接的地址, 客商端程序并不会因为这么些改动而发出故障, 这就浏览器采取超媒体响应来报告大家下一步该怎么办.

那么怎么显得这么些link呢?

JSON和XML并未怎么展现link的概念. 不过HTML却知道, anchor成分:

<a href="uri" rel="type"  type="media type">

href包含了URI

rel则汇报了link如何和能源的涉及

type是可选的, 它意味着了媒体的体系

为了扶助HATEOAS, 这个样式就很有用了:

{    ...    "links" : [        {            "rel" : "self",            "href" : http://blog.example.com/posts/{id},            "method" : "GET"        }        ....    ] }

method: 定义了亟需选拔的法子

rel: 注脚了动作的等级次序

href: 包括了实行这些动作所包罗的UCR-VI.

为了让ASP.NET Core Web API 辅助HATEOAS, 得须要自身手动编写代码达成. 有三种艺术:

静态类型方案: 必要基类和打包类, 也正是回到的能源里面都蕴含link, 通过接二连三于同四个基类来完毕.

动态类型方案: 要求选取诸如佚名类或ExpandoObject等, 对于单个能源能够使用ExpandoObject, 而对于集结类能源则利用无名类.

应用静态基类包装类

先是创设多个LinkResource,表示链接:

ca88 127

再组建四个架空父类 LinkResourceBase:

ca88 128

它独有叁特性质Links。

下一场本身让CityResource承继于LinkResourceBase:

ca88 129

最终在Controller里面,大家须求写代码来为财富创建上面概念提到的Links。这里也急需用到UrlHelper,供给在Controller里面注入。

ca88 130

出于自己要为Resource成立相当多基于路由的链接地址,所以需求为相关Action的路由填上名字:

ca88 131

接下来在Controller里面创设一个主意,它可感到CityResource增加供给的Links,并重返管理后的CityResource。

ca88 132

先是为能源充分的是自身的链接,这里运用UrlHelper和路由名以及cityId作为参数能够博得href,难道没有须求传递countryId吗?因为Controller的路由地址已经富含了countryId参数,UrlHelper会自动处理这一个题指标;而rel的值能够活动填写,这里笔者用self来代表笔者,API开支者要求领会那部分,通过rel的值,API花费者就能精通API提供了什么效能;最终method的值是GET。

别的多少个链接也是近乎的。遵照要求您能够增添额外的链接,然则针对本文那几个简单的例证,这一个链接就够了。

接下去要做的便是保证每当CityResource被Action重回的时候,都会推行该格局来创制连锁的链接

率先思虑回到单个City的状态,GET:

ca88 133

POST也是完全一样的:

ca88 134

再有八个GetCitiesForCountry那么些方法,它回到的财富的集结,所以小编索要遍历集合,在每五个能源上调用该措施:

ca88 135

此处只须求选用Select方法就可以,它本身就是遍历。

测试,首先是GET单个City:

ca88 136

看起来是OK的,然后在用里面包车型大巴链接测量检验相关操作也是好用的,笔者就不贴图了。

上面测量检验一下POST:

ca88 137

结果也是OK的,链接都是好用的。

末了看一下相会的GET:

ca88 138

看起来勉强能够,集结里的每一种能源都有准确的链接。但是结果里并官样文章针对全体会集的链接。我们也不**能够一贯把结果退换成这几个样子**:

{     value: [city1, city2...]     links: [link1, link2...]    }

因为这是不客观的JSON结果,它并非被呼吁的财富的花色。

不常先不管那点,为了支持集合的HATEOAS,我们要求二个包装类:

ca88 139

这几个类能够当做是指向某系列型的差别平时集结,它一连于LinkResourceBase,具备链接的习性;其余还要保障T的体系也是LinkResourceBase,那样就足以确定保证再次来到的集纳里面包车型客车成分也皆有Links属性;这几个类独有贰个Value属性,类型是IEnumerable<T>。

回来Controller再创制三个办法叫CreateLinksForCities:

ca88 140

ca88 141

小心参数和再次回到类型都以LinkCollectionResourceWrapper。

最后在GET Action方法里调用该方式就可以:

ca88 142

测试:

ca88 143

结果是可以的,未来对于CityResource来讲差不离能够说是永葆HATEOAS了。

行使动态类型

此地要用到dynamic和无名氏类型。

今日CountryController里面包车型客车GET方法再次回到的是IEnumerable<ExpandoObject>,是塑形后的CountryResource:

ca88 144

自身一点计策也施展不出把这种对象承接于某种父类以便加多Links属性。所以这种景色下,就须求使用无名氏类的章程。

此处也是分单个能源和聚众能源两种情状。

单个财富

先是为路由增加好名称:

ca88 145

由于ExpandoObject不能继续小编定义的父类,所以不得不另起炉灶三个形式重返Links:

ca88 146

由于数量塑形的存在,参数还要加上田野s。前面多少个链接很好精通正是Country能源的连锁链接,而后四个能源是Country财富的子能源City的,分别是为Country创设City和获得Country下的Cities。

本条方法标记的大家已经是在驱动应用程序的气象了。那约等于HATEOAS的长处。

接下来就把那一个links增加到响应的body就能够。首先是GET方法:

ca88 147

回来Links,为ExpandoObject增加多个links属性,并回到就可以。

测试:

ca88 148

OK。然后大家增多多少个数据塑形的参数:

ca88 149

照旧OK, self的Link里面的href也带着这几个参数。

然后是POST Action的方法:

ca88 150

和GET大约,只可是POST不供给多少塑形。注意重回的CreatedAtRoute里面的第1个参数里面包车型客车id,小编是从linkedCountryResource里面收取来的,实际不是countryModel的id,那样做恐怕更加好,因为那些id应该是linkedCountryResource里面包车型客车。

测试:

ca88 151

结果也是OK的。

汇聚能源

事先大家对GetCountries做了翻页的管理,何况把翻页的元数据放在了响应的Header里面,况兼在那之中包含了前一页和后一页的链接:

ca88 152

实际上那四个链接放在Links集结里是更加好的,所以上边这些方法会增多前一页和后一页的链接:

ca88 153

那边运用了事先创造的CreateCountryUri方法,分别再次回到了self和前一页以及后一页。

末段在GetCountries方法里调用:

ca88 154

首先把元数据里面包车型客车四个链接去掉了。

接下来为集聚成立了links,再然后对集中举行数据塑形,并把集合里面的种种对象都拉长了links。最终回来三个带有value和links的佚名类。

测试:

ca88 155

ca88 156

不容置疑的归来了结果。

上面测量检验一下各类参数:

ca88 157

ca88 158

结果应当是OK的,然而大小写貌似有一对标题,这一个自家直接在源码里面改吧。

此间介绍了二种方法,其实在类型中依据景况照旧利用一种相比好。

Media Type

针对响应的结果,其描述性的数额依旧叫元数据应该献身Header里面。举个例子以前做翻页的时候,总页数,当前页数等数据都位居了Header里面;而下一页和上一页的链接则位居了响应的body里面。那那多少个链接应该是能源的一有的吗?可能说他们是否对能源开展了描述?别的的链接也设有那么些难题。倘若是元数据,那么就活该投身Header,假诺是财富的一部分,就足以放在响应的body里。未来的景色是,上例和事先的写法是对同样种能源的两样表明。不过到近来我们恳请的Accept Header都以application/json,也正是想要能源的JSON表述,可是回去的并非Country能源的表述,而是其余一种东西,它在Country能源的JSON表述的基本功上还存有links属性,所以说只要大家呼吁的是application/json,那么links就不该是能源的一有的。

实在今后回到的东西是另一种media type并不是application/json,那样我们就破坏了财富的自己描述性那合同束各类音讯都应该富含丰裕的音讯以便让别的东西知道什么样管理该音讯)。所以咱们再次回到的content-type的类型是错误的,并且还只怕会招致API花费者不可能从content-type的项目来科学的剖判响应,也正是说小编从未告诉API成本者哪些来管理那几个结果。那么施工方案正是创造新的media type。

Vendor-specific media type 供应商特定媒体类型

它的社团概况上如下:

application/vnd.mycompany.hateoas json

先是有的vnd是vendor的缩写,这一条是mime type的尺度,表示这几个媒体类型是经销商特定的。

接下去是自定义的标记,也或然还包蕴额外的值,这里自个儿是用的是公司名,随后是hateoas表示回去的响应里面要包蕴链接。

最终是二个“ json”。

任何那几个media type就象征小编所急需的财富表述是JSON格式的,何况还要带着相关链接。

于是当呼吁的media type是application/json的时候,只需要再次来到能源的JSON表述。

而诉求application/vnd.mycompany.hateoas json的时候,供给回到带有链接的能源表述。

修改Action方法:

ca88 159

ca88 160

应用FromHeader读取Header里面包车型地铁Accept的值,然后剖断若是media type是自定义的,那么正是包括链接的结果;不然,就利用不包涵链接的结果,而且把翻页相关的链接放在自定义的Header里面。

测试:

ca88 161

伏乞application/json,再次来到结果不带links。

修改media type:

ca88 162

再次来到的是406,Not Acceptable。

那是因为ASP.NET Core的格式化器并不认得大家那几个自定义的媒体类型。

在Startup里面增多这两句话以支撑这几个媒体类型:

ca88 163

然后再测量试验:

ca88 164

ca88 165

这段时间就对了。

根文档

RESTful的API必要为API的顾客提供五个根文档。通过那些文书档案,API消费者能够领悟怎么与另外的API举行互动。能够把那一个驾驭为索引页面吗。

本条文书档案位于API的根部,建立一个RootController:

ca88 166

它的路由地址便是根路线/api。

它独有一个GET方法,通过读取Header里的Accept的值,来回到相应的链接。

此间借使媒体类型是本身前边自定义的格外,就能够重返多少个链接:本人,获取Countries,创立Country。那四个就够用了,有了那三个链接,其它的操作和能源的路由地址都会因而一斑斑的链接得到到。

一经伏乞类型是别的的,就回来204。

出于自个儿这些顺序太简单了,所以那边只写那么些内容就丰硕了。

于今,关于财富的表述以及媒体类型你或然会开掘越来越多的标题。

看前边的事例里面包车型地铁Links链接,那几个链接的格式而不是某些职业的格式,而是自个儿要好创设的格式,花费者API并不知道如何管理那些Link,开销者API须求从API文书档案中打听怎么分析Link,作者索要在API文档里描述rel的值。

笔者们也驾驭媒体类型media type也是API的对外接口合约的开始和结果。这里还应该有其他贰个主题材料,超媒体允许程序控件、链接等在被亟需的时候提供,针对有个别动作的链接,API费用者并不知道应该在伸手里放什么内容。

前面大家已经创办了自定义的媒体类型,回想一下Country的GET和POST八个Action,它们选择的是差别的ResourceModel:

ca88 167

ca88 168

纵然自身的例子里它们的性质很像,不过它们是例外的Model,何况有希望属性差距相当的大。

接下来在八个Action里,小编都以用的是application/json这几个媒体类型,实际上这些类别里近些日子好些个的API作者都以用的是application/json。不过事实上这一个Model是对Country那几个能源的差异表明,使用application/json实际上是不当的。应该利用vendor-specific的传播媒介类型,举个例子:

application/vnd.mycompany.country.display json和application/vnd.mycompany.country.create json。依照境况也能够做的越来越细越来越灵活一些。那样API花费者多少理解了针对性差别动作应该发送什么样的央求内容了。

版本

大家的API到后天一度转移了无多次,API肯定会转移,所以须要版本的插手。

API的机能,业务逻辑,乃至Resource Model都会爆发变化,可是大家供给保障变化的同有时间不要对API的主顾产生破坏。

拓宽版本调控的章程有多少个:

  • 在Uri里面插入版本:/api/v1/countries
  • 通过query string 查询字符串:/api/countries?api-version=v1
  • 自定义Header:例如:”api-version“=v1

可是在RESTful的社会风气里,这么些做法不是都得以的。

骨子里罗伊 Fielding建议不用对RESTful API进行版本管理

不过事实上相当多个人感到照旧须要对API实行版本管理的,因为必要必然会直接变化的,API就能够平昔变化。可是也毫无对其他事物都开展版本管理,大家理应尽大概小心的选择版本,尽量使API向下包容

假如API的法力或作业逻辑变化了,HATEOAS会把那事管理很好, API的花费者通过观看HATEOAS的那些事物,就不会对它导致损坏。

但是如果Resource Model变化了,那的确是个难点,罗伊Fielding说这种场合也不应当进行版本管理

那一个实际正是事先的标题,小编怎么着让API的花费者知晓能源的表述应该是怎样的;还应该有自身何以保障随着API的向上,API的主顾也会随之进化?

依赖罗伊 Fielding的解说,这个难点的缓慢解决方案就是运用按需编码约束(Code on 德姆and)来适配媒体类型和财富表述的开垦进取,约束中涉及API能够扩充顾客端的效劳。

可能在ASP.NET MVC可能局地web网址能够自适应这种转变,若是这一个网址的js,html等是从服务器端生成的;不过大多数的时候,其实很难落实这种自适应变化。

咱俩恐怕能够在传播媒介类型里加多版本号来适合管理财富表述的变化。举个例子:

application/vnd.mycompany.country.display.v1 json和application/vnd.mycompany.country.display.v2 json

上面举个例子, 作者在Entity Model里面增多了三个新的属性大洲 Continent,当然它是可空的:

ca88 169

方今日API的买主能够在成立Country的时候给Continent赋值也足以不赋值,这时,就需求再创制三个包罗Continent属性的ResourceModel为POST这几个动作:

ca88 170

别忘了做AutoMapper的映照配置。

在Controller里,针对POST动作它的参数类型或然是CountryAddResource和CountryAddWithContinentResource,所以还亟需更创设三个POST的办法:

ca88 171

由于有了多少个路由地址同样的POST方法,所以还亟需基于Content-Type这么些Headerd的值来调节须要踏向哪个方法。这里大家得以自定义一个选用于Action方法的自定义约束属性标签:

ca88 172

那么些相当的粗略,传进来须求相配的header类型,和值;然后从request的headers里面找到相称就能够回到true。

分别选择到七个Action:

ca88 173

ca88 174

末段还索要把那多个媒体类型注册一下,注意那三个是输入:

ca88 175

下边测验,首先使用原本的application/json:

ca88 176

404,没错,因为Content-Type已经不符了。

接下去使用原本的POST方法的媒体类型:

ca88 177

就能步向原本的POST方法:

ca88 178

接纳另贰个传播媒介类型,就可以踏入别的贰个主意,就不贴图了是好用的。

地点的自定义约束标签RequestHeaderMatchingMediaTypeAttribute的第3个参数meidatypes是个数组,为何?

因为,就看上二个截图,那几个措施接收的格式是json,不过只要本身想要也支撑接收xml,就径直在数组里增多另一个xml的媒体类型就能够了。

这么些约束标签不仅能够过滤二个Header类型,也得以多少个,举个例子说作者还要还要根据Accept Header来钦点分化的法子,那么:

ca88 179

这里提示重复,可是能够透过修改那个约束标签类来解决:

ca88 180

此刻,错误提醒就从未有过了:

ca88 181

微软的API Versioning库

微软提供了二个API 版本管理的库:Microsoft.AspNetCore.Mvc.Versioning

利用Nuget安装后,在Startup里面注册:

ca88 182

进而就供给在Controller上标明版本了:

ca88 183

实则笔者并非很心爱这种本子处理,认为会很乱。。有意思味的话,请看一下官方文书档案吧:

继之笔者把那些库删掉了。

而外手动完结的这种HATEOAS,还应该有相当多任何的选项,举个例子OData。但是OData就不然则HATEOAS了,它正在品尝对RESTful API进行规范,举个例子它还对成立Uri、翻页以及调用方法等等都拟定了大多平整,还应该有为数非常多的东西,不过作者或许略微使用OData。

这一次就写到这里,源码在:

上周持续。

编辑:ca88 本文来源:建立规范的ca88

关键词: 亚洲城ca88