.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.mzph.cn/pingmian/62078.shtml

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

相关文章

shiny动态生成颜色选择器并将其用于绘图

在 Shiny 中使用 uiOutput 和 renderUI 动态生成 UI 控件是一种灵活的方法。结合 uiOutput(ns("colorSelectors")) 的用法&#xff0c;可以实现动态生成颜色选择器&#xff0c;并响应用户选择进行绘图或更新显示。 代码 library(shiny) library(colourpicker)# UI …

【单点知识】基于PyTorch进行模型部署

文章目录 0. 前言1. 模型导出1.1 TorchScript1.1.1 使用 torch.jit.trace1.1.2 使用 torch.jit.script 1.2 ONNX1.2.1 导出为 ONNX 格式 1.3 导出后的模型加载1.3.1 加载 TorchScript 模型1.3.2 加载 ONNX 模型 2. 模型优化2.1 模型量化2.2 模型剪枝 3. 服务化部署3.1 Flask 部…

‌Kotlin中的?.和!!主要区别

目录 1、?.和!!介绍 2、使用场景和最佳实践 3、代码示例和解释 1、?.和!!介绍 ‌Kotlin中的?.和!!主要区别在于它们对空指针的处理方式。‌ ‌?.&#xff08;安全调用操作符&#xff09;‌&#xff1a;当变量可能为null时&#xff0c;使用?.可以安全地调用其方法或属性…

java基础知识(常用类)

目录 一、包装类(Wrapper) (1)包装类与基本数据的转换 (2)包装类与String类型的转换 (3)Integer类和Character类常用的方法 二、String类 (1)String类介绍 1)String 对象用于保存字符串,也就是一组字符序列 2)字符串常量对象是用双引号括起的字符序列。例如:&quo…

《Hello YOLOv8从入门到精通》5,颈部网络(Neck)结构、核心源码和参数调优

YOLOv8的颈部网络&#xff08;Neck&#xff09;是目标检测模型中的关键组成部分&#xff0c;它位于骨干网络&#xff08;Backbone&#xff09;和头部网络&#xff08;Head&#xff09;之间&#xff0c;主要负责进行特征融合和增强。 在YOLOv8中&#xff0c;颈部网络采用了先进…

C#里怎么样实现单向链表?

C#里怎么样实现单向链表? 数据结构,是程序基本表示方法。 不同的数据结构,就需要采用不同的算法。 在软件开发中,使用到的链表还是比较多的。不过,目前C#语言,基本上都类库, 所以需要自己创建链表的机会,基本不存在了。 但是作为理解原理,还是学习一下吧。 下面的例…

Servlet细节

目录 1 Servlet 是否符合线程安全&#xff1f; 2 Servlet对象的创建时间&#xff1f; 3 Servlet 绑定url 的写法 3.1 一个Servlet 可以绑定多个url 3.2 在web.xml 配置文件中 url-pattern写法 1 Servlet 是否符合线程安全&#xff1f; 答案&#xff1a;不安全 判断一个线程…

对比三种UI交互界面的方案

在嵌入式系统的显示应用领域&#xff0c;如何高效、稳定地驱动TFT LCD显示屏至关重要。当下主流方案有三种&#xff1a; 单片机控制芯片屏 &#xff0c;常见的是瑞佑系列芯片单片机串口屏&#xff0c;常见迪文和大彩单片机内建LCD驱动&#xff0c;常见比如ST32F429等 这三种各…

w~视觉~3D~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/12538137 #SIF3D 通过两种创新的注意力机制——三元意图感知注意力&#xff08;TIA&#xff09;和场景语义一致性感知注意力&#xff08;SCA&#xff09;——来识别场景中的显著点云&#xff0c;并辅助运动轨迹和姿态的预测…

fastjson不出网打法—BCEL链

前言 众所周知fastjson公开的就三条链&#xff0c;一个是TemplatesImpl链&#xff0c;但是要求太苛刻了&#xff0c;JNDI的话需要服务器出网才行&#xff0c;BCEL链就是专门应对不出网的情况。 实验环境 fastjson1.2.4 jdk8u91 dbcp 9.0.20 什么是BCEL BCEL的全名应该是…

GitLab使用操作v1.0

1.前置条件 Gitlab 项目地址&#xff1a;http://******/req Gitlab账户信息&#xff1a;例如 001/******自己的分支名称&#xff1a;例如 001-master&#xff08;注&#xff1a;master只有项目创建者有权限更新&#xff0c;我们只能更新自己分支&#xff0c;然后创建合并请求&…

MATLAB GUI设计(基础)

一、目的和要求 1、熟悉和掌握MATLAB GUI的基本控件的使用及属性设置。 2、熟悉和掌握通过GUIDE创建MATLAB GUI的方法。 3、熟悉和掌握MATLAB GUI的菜单、对话框及文件管理框的设计。 4、熟悉和掌握MATLAB GUI的M文件编写。 5、了解通过程序创建MATLAB GUI的方法。 二、内…

RabbitMQ简单应用

概念 RabbitMQ 是一种流行的开源消息代理&#xff08;Message Broker&#xff09;软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP - Advanced Message Queuing Protocol&#xff09;。RabbitMQ 通过高效的消息传递机制&#xff0c;主要应用于分布式系统中解耦应用…

第 36 章 - Go语言 服务网格

服务网格&#xff08;Service Mesh&#xff09;是一种管理服务间通信的方法&#xff0c;它允许开发人员对服务之间的交互进行抽象化处理。通过在基础设施层面上实现这一点&#xff0c;服务网格可以帮助解决微服务架构中常见的复杂性和挑战&#xff0c;比如服务发现、负载均衡、…

【es6】原生js在页面上画矩形及删除的实现方法

画一个矩形&#xff0c;可以选中高亮&#xff0c;删除自己效果的实现&#xff0c;后期会丰富下细节&#xff0c;拖动及拖动调整矩形大小 实现效果 代码实现 class Draw {constructor() {this.x 0this.y 0this.disX 0this.disY 0this.startX 0this.startY 0this.mouseDo…

【前端】JavaScript中的隐式声明及其不良影响分析

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;什么是隐式声明&#xff1f;&#x1f4af;隐式声明的常见情景1. 赋值给未声明的变量2. 非严格模式下的隐式声明3. 函数中的变量漏掉声明4. for 循环中的隐式声明5. 使用…

2024小迪安全基础入门第七课

目录 一、抓包技术-Web&App&小程序&PC-扶墙双层 二、 抓包技术-Web&App&小程序&PC-项目联动 三、抓包技术-Web&App&小程序&PC-全局协议 一、抓包技术-Web&App&小程序&PC-扶墙双层 Wireshark&#xff1a; https://www.wir…

在 PyTorch 训练中使用 `tqdm` 显示进度条

在 PyTorch 训练中使用 tqdm 显示进度条 在深度学习的训练过程中&#xff0c;实时查看训练进度是非常重要的&#xff0c;它可以帮助我们更好地理解训练的效率&#xff0c;并及时调整模型或优化参数。使用 tqdm 库来为训练过程添加进度条是一个非常有效的方式&#xff0c;本文将…

windows基础之病毒编写

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

家校通小程序实战教程02口令管理

目录 1 创建数据源2 搭建后台功能3 生成口令4 调用API总结 我们的小程序上线之后&#xff0c;必然面临家长要加入的问题。微搭有登录验证的功能&#xff0c;但是手机验证的机制是&#xff0c;如果你未注册就给你自动注册一个账号&#xff0c;如果以注册了收到验证码就可以登录系…