理解RestfulApi
RestfulAPI简介
REST即Representational state transfer。
RestfulApi实际是一种创建api的风格,或者说是一种约定。它约定在创建api时:使用统一资源占位符表示资源,指定HttpMethod表示对应的操作(例如HttpGet表示获取,HttpPost表示创建,HttpDelete表示删除等),使用Http状态码表示请求结果状态。
关键词定义
- 资源(Resources):是计算机(网络)中的数据,常见形式如图,文,声,像等,对于实际开发中它更多的是指业务数据(存在数据库中的数据)。
- URI(Uniform Resource Identifier):统一资源定位符,我们通过URI即可访问对应的资源。
- 表现层:数据的表现形式(格式)。
- 状态转换:对数据进行操作(增删改查)。
Http常用请求方法
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
以上只列举常用的,当然还有不常用的Http请求方法,例如CONNECT,OPTIONS,HEAD等
Http状态码分类
- 1**:信息,服务器收到请求,需要请求者继续执行操作
- 2**:成功,操作被成功接收并处理
- 3**:重定向,需要进一步的操作以完成请求
- 4**:客户端错误,请求包含语法错误或无法完成请求
- 5**:服务器错误,服务器在处理请求的过程中发生了错误
在NetCore中实现简单的RestfulApi
1.获取资源时一般使用HttpGet,但当参数较大时(一般使用对象承载)可以使用HttpPost
1 /// <summary> 2 /// get product by id 3 /// </summary> 4 /// <param name="id"></param> 5 /// <returns></returns> 6 [HttpGet("{id}")] 7 [ProducesResponseType(StatusCodes.Status200OK)] 8 [ProducesResponseType(StatusCodes.Status200OK)] 9 public async Task<ActionResult<ApiResult<ProductModel>>> GetByIdAsync(Guid id) 10 { 11 try 12 { 13 var productContract = await _productService.GetByIdAsync(id); 14 var productModel = _mapper.Map<ProductModel>(productContract); 15 return GetSuccessResult<ProductModel>(productModel); 16 } 17 catch (Exception ex) 18 { 19 _logger.LogError(ex.ToString()); 20 var internalErrorResult = GetInernalErrorResult(); 21 return BadRequest(internalErrorResult); 22 } 23 }
参数较大时(参数元素多,一般使用对象承载)使用HttpPost
1 [HttpPost("Products")] 2 public async Task<ActionResult<ApiResult<List<ProductModel>>>> MultiGetProductAsync([FromBody]ProductQueryModel model) 3 { 4 try 5 { 6 //TODO query product 7 return null; 8 } 9 catch (Exception ex) 10 { 11 _logger.LogError(ex.ToString()); 12 var internalErrorResult = GetInernalErrorResult(); 13 return BadRequest(internalErrorResult); 14 } 15 }
2.创建对象使用HttpPost
1 [HttpPost] 2 [ProducesResponseType(StatusCodes.Status200OK)] 3 [ProducesResponseType(StatusCodes.Status400BadRequest)] 4 public async Task<ActionResult<ApiResult>> CreateProductAsync(ProductCreateModel model) 5 { 6 ApiResult result = null; 7 if (model == null) 8 { 9 result = GetFailureResult(ApiResultCode.ParameterCannotBeNull, $"parameter can not be null"); 10 return BadRequest(result); 11 } 12 try 13 { 14 var contract = _mapper.Map<ProductCreateContract>(model); 15 await _productService.CreateProductAsync(contract); 16 result = GetSuccessResult(); 17 return result; 18 } 19 catch (PlatformException ex) 20 { 21 _logger.LogError(ex.ToString()); 22 result = GetFailureResult(ex.ErrorCode); 23 return BadRequest(result); 24 } 25 catch (Exception ex) 26 { 27 _logger.LogError(ex.ToString()); 28 var internalErrorResult = GetInernalErrorResult(); 29 return BadRequest(internalErrorResult); 30 } 31 }
3.修改对象用HttpPut
1 [HttpPut("{id}")] 2 [ProducesResponseType(StatusCodes.Status200OK)] 3 [ProducesResponseType(StatusCodes.Status400BadRequest)] 4 public async Task<ActionResult<ApiResult>> UpdateProductAsync(Guid id, ProductEditModel model) 5 { 6 ApiResult result = null; 7 try 8 { 9 var contract = _mapper.Map<ProductEditContract>(model); 10 await _productService.UpdateProductAsync(id, contract); 11 result = GetSuccessResult(); 12 return result; 13 } 14 catch (PlatformException ex) 15 { 16 _logger.LogError(ex.ToString()); 17 result = GetFailureResult(ex.ErrorCode); 18 return BadRequest(result); 19 } 20 catch (Exception ex) 21 { 22 _logger.LogError(ex.ToString()); 23 var internalErrorResult = GetInernalErrorResult(); 24 return BadRequest(internalErrorResult); 25 } 26 }
4.删除使用HttpDelete
1 [HttpPut("{id}")] 2 [ProducesResponseType(StatusCodes.Status200OK)] 3 [ProducesResponseType(StatusCodes.Status400BadRequest)] 4 public async Task<ActionResult<ApiResult>> UpdateProductAsync(Guid id, ProductEditModel model) 5 { 6 ApiResult result = null; 7 try 8 { 9 var contract = _mapper.Map<ProductEditContract>(model); 10 await _productService.UpdateProductAsync(id, contract); 11 result = GetSuccessResult(); 12 return result; 13 } 14 catch (PlatformException ex) 15 { 16 _logger.LogError(ex.ToString()); 17 result = GetFailureResult(ex.ErrorCode); 18 return BadRequest(result); 19 } 20 catch (Exception ex) 21 { 22 _logger.LogError(ex.ToString()); 23 var internalErrorResult = GetInernalErrorResult(); 24 return BadRequest(internalErrorResult); 25 } 26 }
在NetCore中实现Restful风格的API
- 使用HttpGet、HttpPost、HttpPut、HttpDelete等指定请求方式(web api都应该遵循这个约定);
- 有时需要将指定参数限定到url中,用于明确资源。例如HttpGet("{id}");修改资源时HttpPut("{id}")
- 使用ProducesResponseType约定返回Http代码。(请求成功时是Http代码为200,请求失败时是400,也可以自行定义)。
- 使用ActionResult支持返回不同类型,例如BadRequest,Ok等。当直接返回实体结果及其就是默认为Ok。例如【return result;】和【return Ok(result)】是一样的
- 一般接口都是定义为Json格式的,也可以自定义对应的格式类型。
总结
Restful是一种api风格,它约定的URI的定义规范,资源状态转换(增删改查)时应使用对应的HttpMethod进行操作。这样在开发中就可以很明了的知道api的功能,而不会造成不必要的误解。
但是在实际的开发中,其实也可以多对应的扩展,不必太拘泥于这样的规范。不要为了想一个很贴切的URI而耗时半天,也不用因为当查询条件很多时,还一定要使用HttpGet(Url是限定长度的)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律