这里介绍在ASP.NET Core中使用Web API创建 RESTful 服务,本文使用VSCode + NET Core3.0

  1. 创建简单Rest API
  2. 格式化输出
  3. JSON Patch请求
  4. Open API(Swagger)集成

创建简单Rest API

在终端输入

  1. dotnet new webapi -n WebAPI

1. 创建Order模型,然后初始化数据

  1. static List<Models.Order> _orderStore = new List<Models.Order>();
  2. static OrderController()
  3. {
  4. var random = new Random();
  5. foreach (var item in Enumerable.Range(1, 10))
  6. {
  7. _orderStore.Add(new Models.Order
  8. {
  9. Id = item,
  10. OrderNo = DateTime.Now.AddSeconds(random.Next(100, 200)).AddMilliseconds(random.Next(20, 50)).Ticks.ToString(),
  11. Quantity = random.Next(1, 10),
  12. Amount = Math.Round(((decimal)random.Next(100, 500) / random.Next(2, 6)), 2)
  13. });
  14. }
  15. }

View Code

2. 简单REST API接口

  1. /// <summary>
  2. /// 查询所有订单
  3. /// </summary>
  4. [HttpGet]
  5. public ActionResult<List<Models.Order>> GetAll() => _orderStore;
  6. /// <summary>
  7. /// 根据Id查找订单
  8. /// </summary>
  9. [HttpGet("{id:int}")]
  10. public ActionResult<Models.Order> GetById(int id)
  11. {
  12. var order = _orderStore.FirstOrDefault(m => m.Id == id);
  13. if (order == null)
  14. {
  15. return NotFound();
  16. }
  17. return order;
  18. }
  19. /// <summary>
  20. /// 创建订单
  21. /// </summary>
  22. [HttpPost]
  23. public ActionResult<bool> Create(Models.Order order)
  24. {
  25. if (_orderStore.Any(m => m.OrderNo == order.OrderNo))
  26. {
  27. return false;
  28. }
  29. order.Id = _orderStore.Max(m => m.Id) + 1;
  30. _orderStore.Add(order);
  31. return true;
  32. }
  33. /// <summary>
  34. /// 更新订单信息
  35. /// </summary>
  36. [HttpPut]
  37. public ActionResult<bool> Update(Models.Order model)
  38. {
  39. var order = _orderStore.FirstOrDefault(m => m.Id == model.Id);
  40. if (order == null)
  41. {
  42. return NotFound();
  43. }
  44. order.Amount = model.Amount;
  45. order.Quantity = model.Quantity;
  46. return true;
  47. }

View Code

3. 推荐一个VS Code插件(REST Client)测试接口,官方介绍

  1. @baseUrl = https://localhost:5001
  2. ###
  3. GET {{baseUrl}}/Order HTTP/1.1
  4. ###
  5. GET {{baseUrl}}/Order/5 HTTP/1.1
  6. ###
  7. POST {{baseUrl}}/Order HTTP/1.1
  8. Content-Type: application/json
  9. {
  10. "OrderNo": "20191128235769389",
  11. "Quantity": 2,
  12. "Amount": 38.28
  13. }
  14. ###
  15. PUT {{baseUrl}}/Order HTTP/1.1
  16. Content-Type: application/json
  17. {
  18. "Id": 5,
  19. "OrderNo": "20191128235769389",
  20. "Quantity": 2,
  21. "Amount": 38.28
  22. }

View Code

简单介绍一下,

文件后缀是http 或 rest

定义全局变量:@baseUrl = https://localhost:5001   ,注意链接不加引号

### 分割多个请求

POST/PUT 请求紧跟Head请求信息,换行加上请求内容

Ctrl + Alt + R 快捷键 / 点Send Request发起请求
 

格式化输出

Api接口通常会是不同客户端调用,这样会有可能出现需要不同响应格式,例如常用的Json,XML。
ASPNET Core 默认情况下是忽略 Accept 标头,JSON格式返回
一、支持XML格式
1. 添加xml格式化
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllers(options =>
  4. {
  5. options.RespectBrowserAcceptHeader = true; //接受浏览器标头
  6. })
  7. .AddXmlSerializerFormatters(); //添加XMl格式化
  8. }

 2. 请求是添加标头

  1. @orderId = {{order.response.body.*}}
  2. GET {{baseUrl}}/Order/{{orderId}} HTTP/1.1
  3. Accept: text/xml

 若不添加标头,默认使用JSON格式输出

二、URL格式映射

1. 添加[FormatFilter]过滤器,它会检查路由中格式是否存在,并且使用相应的格式化程序输出

2. 路由规则添加{format?}

  1. [ApiController]
  2. [Route("[controller]")]
  3. [FormatFilter]
  4. public class OrderController : ControllerBase
  5. {
  6. [HttpGet("{id:int}.{format?}")]
  7. public ActionResult<Models.Order> GetById(int id)
  8. {
  9. var order = _orderStore.FirstOrDefault(m => m.Id == id);
  10. if (order == null)
  11. {
  12. return NotFound();
  13. }
  14. return order;
  15. }
  16. }

View Code

Url 响应
GET {{baseUrl}}/Order/{{orderId}} HTTP/1.1
JSON(若配置格式化输出)
GET {{baseUrl}}/Order/{{orderId}}.xml
XML(若配置格式化输出)
GET {{baseUrl}}/Order/{{orderId}}.json
JSON(若配置格式化输出)
 
三、添加基于 Newtonsoft.Json 的 JSON 格式支持
 
在ASPNET Core 3.0开始,不再使用Newtonsoft.Json格式化JSON,而是使用System.Text.Json格式化,我们可以替换成Newtonsoft.Json
 
1. 添加包
  1. dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson

 2. 配置Newtonsoft.Json

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllers()
  4. .AddNewtonsoftJson();
  5. }
 
JSON Patch请求

PUT 和 PATCH 方法用于更新现有资源。 它们之间的区别是,PUT 会替换整个资源,而PATCH 仅指定更改。

什么是JSON Patch?

JSON Patch官网 里面有一句介绍的很清楚:JSON Patch is a format for describing changes to a JSON document. (一种描述Json的变化的格式)

什么时候需要用到JSON Patch

  1. 我们返回的JSON很大,修改可能只是某些字段
  2. 对性能要求比较大的地方
  3. 一个大的对象,好几个地方修改,然后统一接口修改

ASPNET Core如何处理JSON Patch 请求

1. 添加包支持

  1. dotnet add package Microsoft.AspNetCore.JsonPatch

2. 使用 HttpPatch 属性进行批注

3. 接受 JsonPatchDocument<T>,通常带有 [FromBody]

4. 调用 ApplyTo 以应用更改

假设我们现在有一个完成订单的需求

  1. 检查金额,数量是否有变更
  2. 更新IsComplete = true

下面附上代码和提交的JSON

控制器代码

  1. [HttpPatch("{orderNo:length(18)}")]
  2. public ActionResult<bool> Update([FromBody] JsonPatchDocument<Models.Order> patchDoc, [FromRoute] string orderNo)
  3. {
  4. var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == orderNo);
  5. patchDoc.ApplyTo(order, ModelState);
  6. if (!ModelState.IsValid)
  7. {
  8. return BadRequest(ModelState);
  9. }
  10. return true;
  11. }

View Code

失败的JSON(金额校验不过)

View Code

 

会在ModelState里面列出校验不过的信息

 成功的JSON

  1. [
  2. {
  3. "op": "test",
  4. "path": "/quantity",
  5. "value": "2"
  6. },
  7. {
  8. "op": "test",
  9. "path": "/amount",
  10. "value": "38.28"
  11. },
  12. {
  13. "op": "add",
  14. "path": "/isComplete",
  15. "value": "true"
  16. },
  17. ]

View Code

我们用Get请求重新查一下,可以看到IsComplete成功被修改了

这里只是简单介绍JSON Patch使用,更多使用方法参考JSON Pan官网微软文档

 

Open API(Swagger)集成

Api 通常需要跟客户端,前端进行沟通,需要编写文档,这需要花费大量时间。

Open Api是专门解决这种问题,它为RESTful api定义了一个标准的、与语言无关的接口,利用工具生成文档,可以做到代码即文档(逼着开发者完善注释)

ASPNET Core 可以使用Swashbuckle.AspNetCoreNSwag 生成Swagger 文档

下面介绍如何使用Swashbuckle.AspNetCore

一、使用Swashbuckle.AspNetCore

    1. dotnet add package Swashbuckle.AspNetCore
  1. 引用命名空间:using Microsoft.OpenApi.Models;

    1. public void ConfigureServices(IServiceCollection services)
    2. {
    3. services.AddSingleton<Models.OrderStore>();
    4. services.AddSwaggerGen(c =>
    5. {
    6. c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web Api Doc", Version = "v1" });
    7. });
    8. }

     

    1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    2. {
    3. app.UseSwagger();
    4. app.UseSwaggerUI(c =>
    5. {
    6. c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    7. });
    8. }

 经过上面两步就可以使用SwaggerUI来查看文档和测试,浏览器打开(http://{url}/swagger)

二、添加XML注释

上面生成的Swagger文档是不包含XML注释,下面介绍如何添加XML注释

  1. <PropertyGroup>
        <GenerateDocumentationFile>true</GenerateDocumentationFile>
        <NoWarn>$(NoWarn);1591</NoWarn>
    </PropertyGroup>

     加上上面生成文档后,未注释的函数,属性会发出警告,警告代码1591,忽略警告可以添加多个,分号分割

    1. /// <summary>
    2. /// 更新订单指定信息
    3. /// </summary>
    4. /// <remarks>
    5. /// Sample request:
    6. /// PATCH /Order/{orderNo}
    7. /// [
    8. /// {
    9. /// "op": "test",
    10. /// "path": "/quantity",
    11. /// "value": "2"
    12. /// },
    13. /// {
    14. /// "op": "test",
    15. /// "path": "/amount",
    16. /// "value": "38.28"
    17. /// },
    18. /// {
    19. /// "op": "add",
    20. /// "path": "/isComplete",
    21. /// "value": "true"
    22. /// },
    23. /// ]
    24. /// </remarks>
    25. /// <returns>返回是否成功</returns>
    26. /// <response code="200">提交成功</response>
    27. /// <response code="400">提交参数异常</response>
    28. /// <response code="400">订单号不存在</response>
    29. [HttpPatch("{orderNo:length(18)}")]
    30. [ProducesResponseType(StatusCodes.Status200OK)]
    31. [ProducesResponseType(StatusCodes.Status404NotFound)]
    32. [ProducesResponseType(StatusCodes.Status400BadRequest)]

    View Code

    ProducesResponseType 描述返回类型

    remarks 会生成请求说明

Web Api 使用就介绍这些,如有错漏,希望指出。

版权声明:本文为WilsonPan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/WilsonPan/p/11945856.html