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

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

创建简单Rest API

在终端输入

dotnet new webapi -n WebAPI

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

public class OrderStore
{
public List<Order> Orders { get; } = new List<Order>(); public OrderStore()
{
var random = new Random();
foreach (var item in Enumerable.Range(, ))
{
Orders.Add(new Order
{
Id = item,
OrderNo = DateTime.Now.AddSeconds(random.Next(, )).AddMilliseconds(random.Next(, )).Ticks.ToString(),
Quantity = random.Next(, ),
Amount = Math.Round(((decimal)random.Next(, ) / random.Next(, )), )
});
}
}
}

2. 简单REST API接口

/// <summary>
/// 订单模块
/// </summary>
[ApiController]
[Route("[controller]")]
[FormatFilter]
public class OrderController : ControllerBase
{ readonly Models.OrderStore _orderStore = null;
public OrderController(Models.OrderStore orderStore)
{
_orderStore = orderStore;
} /// <summary>
/// 查询所有订单
/// </summary>
[HttpGet]
public ActionResult<List<Models.Order>> GetAll() => _orderStore.Orders; /// <summary>
/// 获取订单
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id:int}.{format?}")]
public ActionResult<Models.Order> GetById(int id)
{
var order = _orderStore.Orders.FirstOrDefault(m => m.Id == id); if (order == null)
{
return NotFound();
} return order;
} /// <summary>
/// 创建订单
/// </summary>
/// <param name="order"></param>
/// <returns>成功返回订单Id,失败返回-1</returns>
[HttpPost]
public ActionResult<int> Create(Models.Order order)
{
if (_orderStore.Orders.Any(m => m.OrderNo == order.OrderNo))
{
return -;
} order.Id = _orderStore.Orders.Max(m => m.Id) + ;
_orderStore.Orders.Add(order); return order.Id;
} /// <summary>
/// 更新订单
/// </summary>
/// <returns></returns>
[HttpPut]
public ActionResult<bool> Update(Models.Order model)
{
Console.WriteLine($"OrderNo:{model.OrderNo}");
var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == model.OrderNo); if (order == null)
{
return NotFound();
} order.Amount = model.Amount;
order.Quantity = model.Quantity; return true;
} /// <summary>
/// 更新订单指定信息
/// </summary>
/// <remarks>
/// Sample request:
///
/// PATCH /Order/{orderNo}
/// [
/// {
/// "op": "test",
/// "path": "/quantity",
/// "value": "2"
/// },
/// {
/// "op": "test",
/// "path": "/amount",
/// "value": "38.28"
/// },
/// {
/// "op": "add",
/// "path": "/isComplete",
/// "value": "true"
/// },
/// ]
/// </remarks>
/// <returns>返回是否成功</returns>
/// <response code="200">提交成功</response>
/// <response code="400">提交参数异常</response>
/// <response code="404">订单号不存在</response>
[HttpPatch("{orderNo:length(18)}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<bool> Update([FromBody] JsonPatchDocument<Models.Order> patchDoc, [FromRoute] string orderNo)
{
var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == orderNo); if (order == null)
{
return NotFound();
} patchDoc.ApplyTo(order, ModelState); if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} return Ok(true);
}
}

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

@baseUrl = https://localhost:5001

###
GET {{baseUrl}}/Order HTTP/1.1 ###
# @name order
POST {{baseUrl}}/Order HTTP/1.1
Accept: application/json
Content-Type: application/json {
"OrderNo": "",
"Quantity": ,
"Amount": 38.28
} ### @orderId = {{order.response.body.*}}
GET {{baseUrl}}/Order/{{orderId}}.json HTTP/1.1 ###
GET {{baseUrl}}/Order/{{orderId}}.xml HTTP/1.1
###
GET {{baseUrl}}/Order/{{orderId}} HTTP/1.1
### PUT {{baseUrl}}/Order HTTP/1.1
Content-Type: application/json
Accept: application/json {
"Id": ,
"OrderNo": "",
"Quantity": ,
"Amount": 38.28
} ### GET {{baseUrl}}/Order/ ### PATCH {{baseUrl}}/Order/ HTTP/1.1
Accept: application/json
Content-Type: application/json [
{
"op": "test",
"path": "/quantity",
"value": ""
},
{
"op": "test",
"path": "/amount",
"value": "38.28"
},
{
"op": "add",
"path": "/isComplete",
"value": "true"
},
] Sample request: PATCH /Order/{orderNo} [
{
"op": "test",
"path": "/quantity",
"value": ""
},
{
"op": "test",
"path": "/amount",
"value": "38.28"
},
{
"op": "add",
"path": "/isComplete",
"value": "true"
},
]

简单介绍一下,

文件后缀是http 或 rest

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

### 分割多个请求

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

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

格式化输出

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

2. 请求是添加标头

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

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

二、URL格式映射

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

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

[HttpGet("{id:int}.{format?}")]
public ActionResult<Models.Order> GetById(int id)
{
var order = _orderStore.Orders.FirstOrDefault(m => m.Id == id); if (order == null)
{
return NotFound();
} return order;
}
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. 添加包
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson

2. 配置Newtonsoft.Json

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson(options => //添加基于NewtonsoftJson格式化
{
options.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
}
 
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. 添加包支持

dotnet add package Microsoft.AspNetCore.JsonPatch

2. 使用 HttpPatch 属性进行批注

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

4. 调用 ApplyTo 以应用更改

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

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

下面附上代码和提交的JSON

控制器代码

[HttpPatch("{orderNo:length(18)}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<bool> Update([FromBody] JsonPatchDocument<Models.Order> patchDoc, [FromRoute] string orderNo)
{
var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == orderNo); if (order == null)
{
return NotFound();
} patchDoc.ApplyTo(order, ModelState); if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} return Ok(true);
}

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

PATCH  {{baseUrl}}/Order/ HTTP/1.1
Accept: application/json
Content-Type: application/json [
{
"op": "test",
"path": "/quantity",
"value": ""
},
{
"op": "test",
"path": "/amount",
"value": "38.28"
},
{
"op": "add",
"path": "/isComplete",
"value": "true"
},
]

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

成功的JSON

PATCH  {{baseUrl}}/Order/ HTTP/1.1
Accept: application/json
Content-Type: application/json [
{
"op": "test",
"path": "/quantity",
"value": ""
},
{
"op": "test",
"path": "/amount",
"value": "36.8"
},
{
"op": "add",
"path": "/isComplete",
"value": "true"
},
]

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

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

Open API(Swagger)集成

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

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

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

下面介绍如何使用Swashbuckle.AspNetCore

一、使用Swashbuckle.AspNetCore

  1. 安装Swashbuckle.AspNetCore包

    dotnet add package Swashbuckle.AspNetCore
  2. 添加并配置 Swagger 中间件

    引用命名空间:using Microsoft.OpenApi.Models;

    services.AddSingleton<Models.OrderStore>();
    
    services.AddSwaggerGen(c =>
    {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web Api Doc", Version = "v1" });
    });
    app.UseSwagger();
    
    app.UseSwaggerUI(c =>
    {
      c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

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

二、添加XML注释

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

  1. 项目文件(*.csproj)添加以下

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

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

  2. AddSwaggerGen添加下面XML支持

    services.AddSwaggerGen(c =>
    {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web Api Doc", Version = "v1" }); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath);
    });
  3. 方法添加注释

    /// <summary>
    /// 更新订单指定信息
    /// </summary>
    /// <remarks>
    /// Sample request:
    ///
    /// PATCH /Order/{orderNo}
    /// [
    /// {
    /// "op": "test",
    /// "path": "/quantity",
    /// "value": "2"
    /// },
    /// {
    /// "op": "test",
    /// "path": "/amount",
    /// "value": "38.28"
    /// },
    /// {
    /// "op": "add",
    /// "path": "/isComplete",
    /// "value": "true"
    /// },
    /// ]
    /// </remarks>
    /// <returns>返回是否成功</returns>
    /// <response code="200">提交成功</response>
    /// <response code="400">提交参数异常</response>
    /// <response code="404">订单号不存在</response>

    ProducesResponseType 描述返回类型

    remarks 会生成请求说明

  4. 效果

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

转发请标明出处:https://www.cnblogs.com/WilsonPan/p/11945856.html

示例代码:https://github.com/WilsonPan/AspNetCoreExamples/tree/master/WebApi

【ASP.NET Core学习】Web API的更多相关文章

  1. angular4和asp.net core 2 web api

    angular4和asp.net core 2 web api 这是一篇学习笔记. angular 5 正式版都快出了, 不过主要是性能升级. 我认为angular 4还是很适合企业的, 就像.net ...

  2. 温故知新,使用ASP.NET Core创建Web API,永远第一次

    ASP.NET Core简介 ASP.NET Core是一个跨平台的高性能开源框架,用于生成启用云且连接Internet的新式应用. 使用ASP.NET Core,您可以: 生成Web应用和服务.物联 ...

  3. 使用angular4和asp.net core 2 web api做个练习项目(一)

    这是一篇学习笔记. angular 5 正式版都快出了, 不过主要是性能升级. 我认为angular 4还是很适合企业的, 就像.net一样. 我用的是windows 10 安装工具: git for ...

  4. 使用angular4和asp.net core 2 web api做个练习项目(四)

    第一部分: http://www.cnblogs.com/cgzl/p/7755801.html 第二部分: http://www.cnblogs.com/cgzl/p/7763397.html 第三 ...

  5. 基于ASP.NET Core 创建 Web API

    使用 Visual Studio 创建项目. 文件->新建->项目,选择创建 ASP.NET Core Web 应用程序. 基于 ASP.NET Core 2.0 ,选择API,身份验证选 ...

  6. ASP.NET Core Restful Web API 相关资源索引

    GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...

  7. 使用angular4和asp.net core 2 web api做个练习项目(二), 这部分都是angular

    上一篇: http://www.cnblogs.com/cgzl/p/7755801.html 完成client.service.ts: import { Injectable } from '@an ...

  8. 使用 ASP.NET Core 创建 Web API及链接sqlserver数据库

    创建 Web API https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.0& ...

  9. 使用angular4和asp.net core 2 web api做个练习项目(三)

    第一部分: http://www.cnblogs.com/cgzl/p/7755801.html 第二部分: http://www.cnblogs.com/cgzl/p/7763397.html 后台 ...

  10. ASP.NET Core 中基于 API Key 对私有 Web API 进行保护

    这两天遇到一个应用场景,需要对内网调用的部分 web api 进行安全保护,只允许请求头账户包含指定 key 的客户端进行调用.在网上找到一篇英文博文 ASP.NET Core - Protect y ...

随机推荐

  1. Rest_Framework之频率组件部分

    一.RestFramework之频率组件源码部分 频率组件的源码部分和权限组件流程一模一样的,这里就不多说了,直接上源码的主要逻辑部分: def check_throttles(self, reque ...

  2. 加上cdn后字体跨域

    @font-face是CSS3中的一个特性,可以把自己定义的Web字体嵌入到网页中,随着@font-face,越来越多的网页采用字体图标作为网页中的小图形. 比如Bootstrap就采用了Glyphi ...

  3. TOMACT 各个版本集合

    http://archive.apache.org/dist/tomcat/ 再点击 bin 目录,找到想下载的即可

  4. windows 360浏览器打开网站白屏

    1.场景 使用windows的360浏览器打开网页白屏 使用mac 谷歌,360,火狐浏览器打开均正常 2.原因 windows浏览器默认使用的是ie浏览器内核渲染的,js执行时发生错误 3.添加he ...

  5. Docker的Ubuntu16.04容器如何汉化

    最近发现docker hub中的vnc镜像大部分是没有安装语言包的,试了好多天才把他搞出来. 下面为实现步奏. 网盘软件地址 ://pan.baidu.com/share/link?shareid=3 ...

  6. 大数据之路day01_2--记事本与EditPlus编写Hello World并且运行

    在上一节我们成功的安装JAVA并且将其环境配置成功,接下来我们来编写第一个java程序——Hello World 1.利用记事本编写代码,利用命令行来编译运行 (1)新建记事本,(文件名).java后 ...

  7. 学习笔记之vim的使用

    很多刚学习linux编程的人总是对vim有一种恐惧,我自己就是这么回事的. 可是当你努力的去尝试学习使用后,才发现它的精髓所在. 在我看来,让vim变得好用的前提是要安装两个插件,ctags和tagl ...

  8. 1011课堂小结 day21

    组合 什么是组合 组合指的是一个对象中的属性,是另一个对象. 为什么要使用组合 为了减少代码冗余 封装 什么是封装 封装指的是把一堆属性(特征与技能)封装到一个对象中 为什么要封装 封装的目的为了方便 ...

  9. linux引导之grub2

    先了解下什么是Bootloader 以下是百度百科释意 在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行.可以初始化硬件设备.建立内存空间映射图,从而将系统的软硬件环境带到一个合适 ...

  10. java多线程回顾1:线程的概念与创建

    1.进程与线程的概念 现在几乎所有操作系统都支持多任务,通常一个任务就是一个程序,一个运行中的程序就是一个进程.当一个程序行时,其内部也可能在执行多个任务,进程内每一个任务的执行流,就是一个线程. 所 ...