.NET9 - Swagger平替Scalar详解(四)

书接上回,上一章介绍了Swagger代替品Scalar,在使用中遇到不少问题,今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。

下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。

在这里插入图片描述

01、版本说明

我们先来看看默认添加后是什么样子的。

public static void Main(string[] args)
{var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();builder.Services.AddOpenApi();var app = builder.Build();app.MapScalarApiReference();app.MapOpenApi();app.UseAuthorization();app.MapControllers();app.Run();
}

效果如下:

在这里插入图片描述

我们可以直接修改builder.Services.AddOpenApi()这行代码,修改这块描述,代码如下:

builder.Services.AddOpenApi(options =>
{options.AddDocumentTransformer((document, context, cancellationToken) =>{document.Info = new(){Title = "订单微服务",Version = "v1",Description = "订单相关接口"};return Task.CompletedTask;});
});

我们再来看看效果。

在这里插入图片描述

02、接口分类

通过上图可以看到菜单左侧排列着所有接口,现在我们可以通过Tags特性对接口进行分类,如下图我们把增删改查4个方法分为幂等接口和非幂等接口两类,如下图:

在这里插入图片描述

然后我们看看效果,如下图:

在这里插入图片描述

03、接口描述

之前使用Swagger我们都是通过生成的注释XML来生成相关接口描述,现在则是通过编码的方式设置元数据来生成相关描述。

可以通过EndpointSummary设置接口摘要,摘要不设置默认为接口url,通过EndpointDescription设置接口描述,代码如下:

//获取
[HttpGet(Name = "")]
[Tags("幂等接口")]
[EndpointDescription("获取订单列表")]
public IEnumerable<Order> Get()
{return null;
}
//删除
[HttpDelete(Name = "{id}")]
[Tags("幂等接口")]
[EndpointSummary("删除订单")]
[EndpointDescription("根据订单id,删除相应订单")]
public bool Delete(string id)
{return true;
}

运行效果如下:

在这里插入图片描述

04、参数描述

同样可以通过Description特性来设置参数的描述,并且此特性可以直接作用于接口中参数之前,同时也支持作用于属性上,可以看看下面示例代码。

public class Order
{[property: Description("创建日期")]public DateOnly Date { get; set; }[property: Required][property: DefaultValue(120)][property: Description("订单价格")]public int Price { get; set; }[property: Description("订单折扣价格")]public int PriceF => (int)(Price * 0.5556);[property: Description("商品名称")]public string? Name { get; set; }
}
[HttpPut(Name = "{id}")]
[Tags("非幂等接口")]
public bool Put([Description("订单Id")] string id, Order order)
{return true;
}

效果如下图:

在这里插入图片描述

从上图可以发现除了描述还有默认值、必填项、可空等字样,这些是通过其他元数据设置的,对于属性还有以下元数据可以进行设置。

在这里插入图片描述

05、枚举类型

对于枚举类型,我们正常关注两个东西,其一为枚举项以int类型展示还是以字符串展示,其二为枚举项显示描述信息。

关于第一点比较简单只要对枚举类型使用JsonStringEnumConverter即可,代码如下:

[JsonConverter(typeof(JsonStringEnumConverter<OrderStatus>))]
public enum OrderStatus
{[Description("等待处理")]Pending = 1,[Description("处理中")]Processing = 2,[Description("已发货")]Shipped = 3,[Description("已送达")]Delivered = 4,
}

效果如下:

在这里插入图片描述

通过上图也可以引发关于第二点的需求,如何对每个枚举项添加描述信息。

要达到这个目标需要做两件事,其一给每个枚举项通过Description添加元数据定义,其二我们要修改文档的数据结构Schema。

修改builder.Services.AddOpenApi(),通过AddSchemaTransformer方法修改文档数据结构,代码如下:

options.AddSchemaTransformer((schema, context, cancellationToken) =>
{//找出枚举类型if (context.JsonTypeInfo.Type.BaseType == typeof(Enum)){var list = new List<IOpenApiAny>();//获取枚举项foreach (var enumValue in schema.Enum.OfType<OpenApiString>()){//把枚举项转为枚举类型if (Enum.TryParse(context.JsonTypeInfo.Type, enumValue.Value, out var result)){//通过枚举扩展方法获取枚举描述var description = ((Enum)result).ToDescription();//重新组织枚举值展示结构list.Add(new OpenApiString($"{enumValue.Value} - {description}"));}else{list.Add(enumValue);}}schema.Enum = list;}return Task.CompletedTask;
});

我们再来看看结果。

在这里插入图片描述

但是这也带来了一个问题,就是参数的默认值也是添加描述的格式,显然这样的数据格式作为参数肯定是错误的,因此我们需要自己注意,如下图。目前我也没有发现更好的方式即可以把每项枚举描述加上,又不影响参数默认值,有解决方案的希望可以不吝赐教。

在这里插入图片描述

06、文件上传

下面我们来看看文件上传怎么用,直接上代码:

[HttpPost("upload/image")]
[EndpointDescription("图片上传接口")]
[DisableRequestSizeLimit]
public bool UploadImgageAsync(IFormFile file)
{return true;
}

然后我们测试一下效果。

在这里插入图片描述

首先我们可以看到请求示例中相关信息,这个相当于告诉我们后面要怎么选择文件上传,我们继续点击Test Request。

首先请求体需要选择multipart/form-data,上图请求示例中已经给出提示。

在这里插入图片描述

然后设置key为file,上图请求示例中已经给出提示,然后点击File上传图片,最后点击Send即可。

在这里插入图片描述

07、JWT认证

最后我们来看看如何使用JWT认证,

首先我们需要注入AddAuthentication及AddJwtBearer,具体代码如下:

public class JwtSettingOption
{//这个字符数量有要求,不能随便写,否则会报错public static string Secret { get; set; } = "123456789qwertyuiopasdfghjklzxcb";public static string Issuer { get; set; } = "asdfghjkkl";public static string Audience { get; set; } = "zxcvbnm";public static int Expires { get; set; } = 120;public static string RefreshAudience { get; set; } = "zxcvbnm.2024.refresh";public static int RefreshExpires { get; set; } = 10080;
}
builder.Services.AddAuthentication(options =>
{options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{//取出私钥var secretByte = Encoding.UTF8.GetBytes(JwtSettingOption.Secret);options.TokenValidationParameters = new TokenValidationParameters(){//验证发布者ValidateIssuer = true,ValidIssuer = JwtSettingOption.Issuer,//验证接收者ValidateAudience = true,ValidAudiences = new List<string> { JwtSettingOption.Audience, JwtSettingOption.Audience },//验证是否过期ValidateLifetime = true,//验证私钥IssuerSigningKey = new SymmetricSecurityKey(secretByte),ClockSkew = TimeSpan.FromHours(1), //过期时间容错值,解决服务器端时间不同步问题(秒)RequireExpirationTime = true,};
});

然后我们需要继续修改builder.Services.AddOpenApi()这行代码,在里面加上如下代码:

在这里插入图片描述

其中BearerSecuritySchemeTransformer实现如下:

public sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken){var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();if (authenticationSchemes.Any(authScheme => authScheme.Name == JwtBearerDefaults.AuthenticationScheme)){var requirements = new Dictionary<string, OpenApiSecurityScheme>{[JwtBearerDefaults.AuthenticationScheme] = new OpenApiSecurityScheme{Type = SecuritySchemeType.Http,Scheme = JwtBearerDefaults.AuthenticationScheme.ToLower(),In = ParameterLocation.Header,BearerFormat = "Json Web Token"}};document.Components ??= new OpenApiComponents();document.Components.SecuritySchemes = requirements;foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations)){operation.Value.Security.Add(new OpenApiSecurityRequirement{[new OpenApiSecurityScheme{Reference = new OpenApiReference{Id = JwtBearerDefaults.AuthenticationScheme,Type = ReferenceType.SecurityScheme}}] = Array.Empty<string>()});}}}
}

下面就可以通过[Authorize]开启接口认证,并实现一个登录接口获取token用来测试。

[HttpPost("login")]
[EndpointDescription("登录成功后生成token")]
[AllowAnonymous]
public string  Login()
{//登录成功返回一个token// 1.定义需要使用到的Claimsvar claims = new[] { new Claim("UserId", "test") };// 2.从 appsettings.json 中读取SecretKeyvar secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettingOption.Secret));// 3.选择加密算法var algorithm = SecurityAlgorithms.HmacSha256;// 4.生成Credentialsvar signingCredentials = new SigningCredentials(secretKey, algorithm);var now = DateTime.Now;var expires = now.AddMinutes(JwtSettingOption.Expires);// 5.根据以上,生成tokenvar jwtSecurityToken = new JwtSecurityToken(JwtSettingOption.Issuer,         //IssuerJwtSettingOption.Audience,       //Audienceclaims,                          //Claims,now,                             //notBeforeexpires,                         //expiressigningCredentials               //Credentials);// 6.将token变为stringvar token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);return token;
}

下面我们先用登录接口获取一个token。

在这里插入图片描述

我们先用token调用接口,可以发现返回401。

在这里插入图片描述

然后我们把上面获取的token放进去,请求成功。

在这里插入图片描述

在这个过程中有可能会遇到一种情况:Auth Type后面的下拉框不可选,如下图。

在这里插入图片描述

可能因以下原因导致,缺少[builder.Services.AddAuthentication().AddJwtBearer();]或[options.AddDocumentTransformer();]任意一行代码。

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479037.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算(a+b)/c的值

计算&#xff08;ab&#xff09;/c的值 C语言代码C语言代码Java语言代码Python语言代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 给定3个整数a、b、c&#xff0c;计算表达式(ab)/c的值&#xff0c;/是整除运算。 输入 输入仅一行&…

PICO 获取设备号 SN码

Unity版本 2020.3.42f1c1PICO SDK版本PICO Unity Integration SDK-3.0.5-20241105Pico设备pico 4ultra 注意 此api暂时只测试企业版本 pico 4ultra 代码 using Unity.XR.PICO.TOBSupport;private void Awake() {bool result PXR_Enterprise.InitEnterpriseService();Debug.L…

【大数据技术基础】 课程 第8章 数据仓库Hive的安装和使用 大数据基础编程、实验和案例教程(第2版)

第8章 数据仓库Hive的安装和使用 8.1 Hive的安装 8.1.1 下载安装文件 访问Hive官网&#xff08;http://www.apache.org/dyn/closer.cgi/hive/&#xff09;下载安装文件apache-hive-3.1.2-bin.tar.gz 下载完安装文件以后&#xff0c;需要对文件进行解压。按照Linux系统使用的…

[STM32]从零开始的STM32 FreeRTOS移植教程

一、前言 如果能看到这个教程的话&#xff0c;说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗&#xff1f;是的&#xff0c;我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS&#xff0c;再到最…

DAY133权限提升-Windows权限提升篇溢出漏洞土豆家族通杀全系补丁对比EXP筛选

知识点 1、Web到Win-系统提权-土豆家族 2、Web到Win-系统提权-人工操作 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移 4、域控权限提升及转移 Windows提权&#xff1a; 1、内核溢出漏洞提权 2、数据库类型提权 3、第三方软件…

web day03 Maven基础 Junit

目录 Maven坐标&#xff1a; 依赖排除&#xff1a; 依赖范围&#xff1a; Maven生命周期&#xff1a; 单元测试&#xff1a; Junit入门&#xff1a; 断言&#xff1a; Junit中的常见注解&#xff1a; 概念&#xff1a;Maven 是一款用于管理和构建 Java项目的工具&#…

day18 结构体

有参宏和函数的区别 1.展开时机&#xff1a;有参宏而言&#xff0c;在预处理阶段展开&#xff0c;而函数在调用时才展开 2.内存使用&#xff1a;有参宏而言&#xff0c;占用的是所在函数的空间&#xff0c;而函数在调用时会单独开辟空间 3.效率上&#xff1a;有参宏的效率比…

44.扫雷第二部分、放置随机的雷,扫雷,炸死或成功 C语言

按照教程打完了。好几个bug都是自己打出来的。比如统计周围8个格子时&#xff0c;有一个各自加号填成了减号。我还以为平移了&#xff0c;一会显示是0一会显示是2。结果单纯的打错了。debug的时候断点放在scanf后面会顺畅一些。中间多放一些变量名方便监视。以及mine要多显示&a…

docker 通过Dockerfile自定义的镜像部署Springboot项目

一、镜像结构介绍&#xff1a; 镜像&#xff1a;层&#xff08;Layer&#xff09;添加安装包、依赖、配置等&#xff0c;每一次操作都形成新的一层&#xff1b;基础镜像&#xff08;BaseImage&#xff09;应用依赖的系统函数库、环境、配置、文件等&#xff1b;入口&#xff0…

全网最早Towards Generalizable Multi-Object Tracking—通用跟踪器的点跟踪CVPR2024

Towards Generalizable Multi-Object Tracking—迈向可推广的多目标跟踪 原标题&#xff1a;Towards Generalizable Multi-Object Tracking 论文链接&#xff1a;https://arxiv.org/pdf/2406.00429 代码链接&#xff1a;https://github.com/qinzheng2000/GeneralTrack.git 作者…

MyBatis框架-动态SQL-XML中的常用标签+特殊字符在XML中的显示

一、if标签、where标签、trim标签、choose标签、set标签、foreach标签 1、问题引入&#xff1a;where关键字和and关键字在动态SQL里面应该如何添加&#xff1f; &#xff08;1&#xff09;if标签&#xff1a; test属性的值是判断条件 if标签里面的内容是条件成立时添加到SQ…

探秘嵌入式位运算:基础与高级技巧

目录 一、位运算基础知识 1.1. 位运算符 1.1.1. 与运算&#xff08;&&#xff09; 1.1.2. 或运算&#xff08;|&#xff09; 1.1.3. 异或运算&#xff08;^&#xff09; 1.1.4. 取反运算&#xff08;~&#xff09; 1.1.5. 双重按位取反运算符&#xff08;~~&#xf…

渗透测试笔记—shodan(7完结)

声明&#xff1a; 学习视频来自B站up主 【泷羽sec】有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&am…

2024年最新版Java八股文复习

最新版本Java八股文复习&#xff0c;每天更新一篇&#xff0c;博主正在持续努力更新中~~~ 一、Java基础篇1、怎么理解面向对象&#xff1f;简单说说封装、继承、多态三大特性&#xff1f;2、多态体现在哪几个方面&#xff1f;3、面向对象的设计原则你知道有哪些吗&#xff1f;4…

Notepad++ 替换所有数字给数字加单引号

前言 今天遇到这样一个场景&#xff1a; 要去更新某张表里 code1,2,3,4,5,6 的数据&#xff0c;把它的 name 设置为 ‘张三’ 但是 code在数据库里面的字段类型是 vachar(64)&#xff0c;它自身携带索引 原本可以这样写 SQL: update tableA set namezhangsan where code in …

前端图像处理(一)

目录 一、上传 1.1、图片转base64 二、图片样式 2.1、图片边框【border-image】 三、Canvas 3.1、把canvas图片上传到服务器 3.2、在canvas中绘制和拖动矩形 3.3、图片(同色区域)点击变色 一、上传 1.1、图片转base64 传统上传&#xff1a; 客户端选择图片&#xf…

推荐一款龙迅HDMI2.0转LVDS芯片 LT6211UX LT6211UXC

龙迅的HDMI2.0转LVDS芯片LT6211UX和LT6211UXC是两款高性能的转换器芯片&#xff0c;它们在功能和应用上有所差异&#xff0c;同时也存在一些共同点。以下是对这两款芯片的详细比较和分析&#xff1a; 一、LT6211UX 主要特性&#xff1a; HDMI2.0至LVDS和MIPI转换器。HDMI2.0输…

51单片机从入门到精通:理论与实践指南入门篇(二)

续51单片机从入门到精通&#xff1a;理论与实践指南&#xff08;一&#xff09;https://blog.csdn.net/speaking_me/article/details/144067372 第一篇总体给大家在&#xff08;全局&#xff09;总体上讲解了一下51单片机&#xff0c;那么接下来几天结束详细讲解&#xff0c;从…

STM32C011开发(3)----Flash操作

STM32C011开发----3.Flash操作 概述硬件准备视频教学样品申请源码下载参考程序生成STM32CUBEMX串口配置堆栈设置串口重定向FLASH数据初始化FLASH 读写演示 概述 STM32C011 系列微控制器内置 Flash 存储器&#xff0c;支持程序存储与数据保存&#xff0c;具备页面擦除、双字写入…

IDEA无法创建java8、11项目创建出的pom.xml为空

主要是由于Spring3.X版本不支持JDK8&#xff0c;JDK11&#xff0c;最低支持JDK17 解决的话要不就换成JDK17以上的版本&#xff0c;但是不太现实 另外可以参考以下方式解决 修改spring初始化服务器地址为阿里云的 https://start.aliyun.com/