.net 温故知新【12】:Asp.Net Core WebAPI 中的Rest风格
RPC
RPC(Remote Procedure Call),远程过程调用),这种RPC形式的API组织形态是类和方法的形式。所以API的请求往往是一个动词用来标识接口的意思,比如 https://xxxx/GetStudent?id=1 和 https://xxxx/AddStudent 这种风格,并且往往没有规范需要我们去查看接口定义文档。HTTP方法基本只用GET和POST,没有使用HTTP的其它谓词设计比较简单。
Rest
Rest:按照Http的语义来使用HTTP协议的一种风格,Rest全称Representational State Transfer(表现层状态转换)。他是一种规范或者设计风格而不是特别的技术。REST形式的API组织形态是资源和实体,请求的路由可以看出对资源的访问,规范统一接口自解释。
比如 https://xxxx/Student/1 用Get方法调用就是获取编号为1的学生。 https://xxxx/Student/1 用Delete调用就是删除编号为1的学生,用delete调用就是删除该学生。
在HTTP中这些调用方法GET、POST、PUT、PATCH、DELETE 即HTTP谓词。GET用来获取资源,POST用来新建资源,PUT用来更新指定资源,PATCH用来批量更新资源,DELETE用来删除资源,通过谓词来表示请求动作或者意图,通过url定位资源。
在请求中GET、PUT、DELETE 请求是幂等的,也就是说可以重试请求。而POST不是幂等,因为POST意思是添加数据。
在Rest风格中使用状态码来标识返回结果,其中常用200、201、400、401、404、410、500等。
ASP.NET Core WebAPI接口
在ASP.NET WebAPI中我们也能看到Rest的风格,理想很丰满,显示很骨干。如果我们严格的按照Rest风格设计接口的话,需要对技术人员有很高的要求,需要去划分不同业务不同的资源定位,而且有些业务也找不到准确的谓词去定义,响应状态码有限无法表达准确的意思,或者是时间上来不及等等原因。
而且这种方式更符合国外语言表达的方式,不太适合我国宝宝体质。
所以我们在设计接口的时候不用非要用Rest风格,我们可以靠近或者在特定的更适合使用Rest接口系统中使用。
本篇我们结合Rest看下接口如何设计和交互。
- 在http接口请求中有三种方式传递参数或者数据。
- URL:资源定位,也就是Rest风格,在请求的url中包含信息,比如https://xxxx/Student/1 1就是学生编号。
- QueryString: URL之外的额外信息,比如RPC中https://xxxx/GetStudent?id=1 id=1就是QueryString
- 请求报文体:供PUT、POST提交提供数据,请求体有多种格式application/x-www-form-urlencoded、multipart/form-data、application/json、text/plain、application/xml。
- 返回状态码
在RPC中Post请求我们习惯如果请求已经在服务器处理,不管处理结果是否正确,我们都返回200状态码。然后在返回数据中用其它信息来标识业务结果。比如{code:1,msg:"成功"}
或者{code:0,msg:"失败"}
。
而在Rest 中Post通常用201返回新增成功,delete 删除的数据不存在返回404,但是404大家知道可能也许是url错误,所以表诉不清。
因此我们在实际设计中可能会进行Rest裁剪,我们既使用RPC的返回结果,同时多用准确的状态码,不用什么都返回200。
使用RPC风格,尽量使用合理谓词,不知道使用什么谓词的时候就用POST,Get Delete参数尽量用资源定位URL,业务错误服务端返回合适的状体吗,不知道返回什么就返回400,如果请求处理成功就用200同时返回结果数据。
在上一篇中遗留的这个问题 .net 温故知新【11】:Asp.Net Core WebAPI 入门使用及介绍
所以我们在Controller中Route配置为[Controller]则不管方法接口名称是什么,仍然以Rest的方式访问。
[Route("[controller]")]
[ApiController]
public class RestCutController : ControllerBase
{
[HttpGet]
public IEnumerable<string> GetStudents()
{
//获取所有学生
return new string[] { "student1", "student2" };
}
[HttpGet("{id}")]
public string GetStudent(int id)
{
//获取id的学生
return "student"+id;
}
[HttpPost]
public void PostStudent([FromBody] string value)
{
//新增
}
[HttpPut("{id}")]
public void PutStudent(int id, [FromBody] string value)
{
//修改
}
[HttpDelete("{id}")]
public void DeleteStudent(int id)
{
//删除id学生
}
}
当我们修改Rout按照RPC方式,[Route("[controller]/[action]")]
运行后发现swagger展示的接口方式就改变了。并且保留了参数URL的方式。
关于返回状态码的问题可以有两种方式,一种是直接在ControllerBase.Response
响应中指定返回状态码。
[HttpDelete("{id}")]
public string DeleteStudent(int id)
{
//删除id学生
if (id == 1)
{
return "删除成功";
}
else {
Response.StatusCode = 404;
return "未找到!";
}
}
另外一种方式就是返回泛型ActionResult<string>
,其中OK
和NotFound
是继承自ActionResult
然后隐式转换到泛型,也可以直接返回IActionResult或者ActionResult但是类型不确定这样swagger文档就不会解析出返回值,所以我们用ActionResult泛型。
[HttpDelete("{id}")]
public ActionResult<string> DeleteStudent(int id)
{
//删除id学生
if (id == 1)
{
return Ok("删除成功");
}
else
{
return NotFound("未找到!");
}
}
[HttpDelete("{id}")]
public ActionResult DeleteStudent(int id) //返回ActionResult
{
//删除id学生
if (id == 1)
{
return Ok("删除成功");
}
else
{
return NotFound("未找到!");
}
}
最后我们在总结下关于API参数获取的方式,在 [HttpGet("{id}")]
中我们看到有{id}
,这个就是占位符,从RUL中获取,不光可以配置占位符还可以配置路径的其它值,甚至可以随意组织,只要我们的参数明和占位符相同就行。
[HttpDelete("number/{id}/Name/{name}")] //自己组织的URL
public ActionResult<string> DeleteStudent(int id,string name)
{
//删除id学生
if (id == 1)
{
return Ok("删除成功");
}
else
{
return NotFound("未找到!");
}
}
当然也可以使用[FromRoute]
从route获取,另外我们还有一些Attribute用于从不同的地方获取参数,比如从QueryString获取。那么我的请求URL就应该是/RestCut/DeleteStudent?id=1
[HttpDelete]
public ActionResult<string> DeleteStudent([FromQuery] int id)
{
//删除id学生
if (id == 1)
{
return Ok("删除成功");
}
else
{
return NotFound("未找到!");
}
}
最后还有[FromHeader]
、[FromForm]
、[FromBody]
这些获取参数的方式,不清楚的使用的时候查询就行了。
.net 温故知新【12】:Asp.Net Core WebAPI 中的Rest风格的更多相关文章
- ASP.NET Core WebAPI中的分析工具MiniProfiler
介绍 作为一个开发人员,你知道如何分析自己开发的Api性能么? 在Visual Studio和Azure中, 我们可以使用Application Insight来监控项目.除此之外我们还可以使用一个免 ...
- Asp.Net Core WebApi中接入Swagger组件(初级)
开发WebApi时通常需要为调用我们Api的客户端提供说明文档.Swagger便是为此而存在的,能够提供在线调用.调试的功能和API文档界面. 环境介绍:Asp.Net Core WebApi + S ...
- .NET Core:在ASP.NET Core WebApi中使用Cookie
一.Cookie的作用 Cookie通常用来存储有关用户信息的一条数据,可以用来标识登录用户,Cookie存储在客户端的浏览器上.在大多数浏览器中,每个Cookie都存储为一个小文件.Cookie表示 ...
- ASP.NET Core WebApi中使用FluentValidation验证数据模型
原文链接:Common features in ASP.NET Core 2.1 WebApi: Validation 作者:Anthony Giretti 译者:Lamond Lu 介绍 验证用户输 ...
- ASP.NET Core WebAPI中使用JWT Bearer认证和授权
目录 为什么是 JWT Bearer 什么是 JWT JWT 的优缺点 在 WebAPI 中使用 JWT 认证 刷新 Token 使用授权 简单授权 基于固定角色的授权 基于策略的授权 自定义策略授权 ...
- Asp.Net Core WebAPI中启用XML格式数据支持
因为XML是一种非常常用的数据格式,所以Asp.Net core提供了非常便利的方式来添加对XML格式的支持 只需要在IOC注册Controller服务的后面跟上.AddXmlDataContract ...
- ASP.NET Core WebApi中简单像素转换跟踪实现
像素跟踪虽然是最早用于跟踪营销转换的方法,但它仍然被广泛使用,像Facebook这样的大公司仍然将其视为跟踪网页转换的方法之一. 由于它的简单性,通过像素方法的跟踪转换仍然被广泛使用.它不需要任何复杂 ...
- 在asp.net core webapi 中开启swagger
首先需要安装包 Swashbuckle.AspNetCore 接着在项目中右键属性 接着在Startup 文件中声明一个字段 private string currentAssemblyName = ...
- Asp.net core WebApi 使用Swagger生成帮助页实例
最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...
- Asp.net core WebApi 使用Swagger生成帮助页
最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...
随机推荐
- 微信Token验证代码的实现
微信开放第三方API接口, 申请地址: https://mp.weixin.qq.com/advanced/advanced?action=interface&t=advanced/inter ...
- vue自定义组件——split-pane
pre { overflow-y: auto; max-height: 500px } github地址: https://github.com/lxmghct/my-vue-components 组 ...
- Spring之丐版IOC实现
文章目录 IOC控制反转 依赖注入 Bean的自动装配方式 丐版IOC实现 BeanDefinition.java ResourceLoader.java BeanRegister.java Bean ...
- cefsharp学习笔记
环境:VS2015+cefsharp 57.0 全部代码如下: 1.要初始化,否则不能刷新 using System; using CefSharp; using System.Collections ...
- 民谣女神唱流行,基于AI人工智能so-vits库训练自己的音色模型(叶蓓/Python3.10)
流行天后孙燕姿的音色固然是极好的,但是目前全网都是她的声音复刻,听多了难免会有些审美疲劳,在网络上检索了一圈,还没有发现民谣歌手的音色模型,人就是这样,得不到的永远在骚动,本次我们自己构建训练集,来打 ...
- 2023-04-11:给你下标从 0 开始、长度为 n 的字符串 pattern , 它包含两种字符,‘I‘ 表示 上升 ,‘D‘ 表示 下降 。 你需要构造一个下标从 0 开始长度为 n + 1 的
2023-04-11:给你下标从 0 开始.长度为 n 的字符串 pattern , 它包含两种字符,'I' 表示 上升 ,'D' 表示 下降 . 你需要构造一个下标从 0 开始长度为 n + 1 的 ...
- 2023-03-16:给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分, 使得所有这些部分表示相同的二进制值。 如果可以做到,请返回任何 [i, j],其中 i+1 < j
2023-03-16:给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分, 使得所有这些部分表示相同的二进制值. 如果可以做到,请返回任何 [i, j],其中 i+1 < ...
- 2022-11-28:给定两个数组A和B,比如 A = { 0, 1, 1 } B = { 1, 2, 3 } A[0] = 0, B[0] = 1,表示0到1有双向道路 A[1] = 1, B[1]
2022-11-28:给定两个数组A和B,比如 A = { 0, 1, 1 } B = { 1, 2, 3 } A[0] = 0, B[0] = 1,表示0到1有双向道路 A[1] = 1, B[1] ...
- 2022-09-08:以下go语言代码输出什么?A:5 66;B:5 88;C:7 88;D:以上都不对。 package main func main() { var x = []int{4:
2022-09-08:以下go语言代码输出什么?A:5 66:B:5 88:C:7 88:D:以上都不对. package main func main() { var x = []int{4:44, ...
- 2022-01-22:力扣411,最短独占单词缩写。 给一个字符串数组strs和一个目标字符串target。target的简写不能跟strs打架。 strs是[“abcdefg“,“ccc“],tar
2022-01-22:力扣411,最短独占单词缩写. 给一个字符串数组strs和一个目标字符串target.target的简写不能跟strs打架. strs是["abcdefg", ...