你知道吗?从 .NET9 开始删除内置的 Swagger 支持 (Swashbuckle)!

.NET 9 中使用 Scalar 替代内置的 Swagger 支持 (Swashbuckle)

  • 为什么 Swagger (Swashbuckle) 被删除?
  • Swagger 的替代方案:Scalar(Scalar.AspNetCore)
  • 如何在 Dotnet 9 中使用它?
  • 如何将 Bearer 身份验证方案添加到 Scalar ?
  • 使用 Scalar 的式例
    • 创建 webapi 项目
    • 安装 nuget 包
    • 添加文件夹目录
    • 修改 Program.cs 文件
  • Scalar 的配置扩展

Microsoft 已决定从 .NET 9 中删除内置的 Swagger 支持 (Swashbuckle)。

为什么 Swagger (Swashbuckle) 被删除?

ASP.NET Core 团队已决定从 .NET 9 中删除内置的 Swagger 支持 (Swashbuckle),原因如下:

  1. 维护问题:Swashbuckle 项目不再由其社区所有者积极维护。问题未得到解决或解决,并且 .NET 8 没有正式版本。
  2. ASP.NET Core 的演变:自从在 .NET 5 中引入 Swagger 支持以来,ASP.NET Core 已经有了显著的发展。它现在内置了对描述 Web API 所需的元数据的支持,从而减少了对外部工具的需求。
  3. 专注于 OpenAPI:该团队希望使 OpenAPI 成为 ASP.NET Core 中的一等公民。他们计划扩展 OpenAPI 文档生成功能,而不依赖外部包。Microsoft.AspNetCore.OpenApi
  4. 替代工具:Visual Studio 现在提供对 .http 文件的内置支持和新的 Endpoints Explorer,从而提供探索、测试和调试 API 的替代方法。
  5. 社区驱动的创新:通过消除默认依赖项,团队鼓励使用和开发可能更适合特定项目需求的各种 OpenAPI 工具。

Swagger 的替代方案:Scalar(Scalar.AspNetCore)

Scalar 是来自 OpenAPI/Swagger 文档的交互式 API 文档。

这个 .NETScalar.AspNetCore 提供了一种基于 OpenAPI/Swagger 文档呈现漂亮的 API引用的简单方法。

Scalar.AspNetCore

您可以在此处获取更多信息。

  • https://github.com/scalar/scalar
  • https://www.nuget.org/packages/Scalar.AspNetCore

如何在 Dotnet 9 中使用它?

1、安装 nuget 包

dotnet add package Scalar.AspNetCore

2、示例用法

using Scalar.AspNetCore;var builder = WebApplication.CreateBuilder(args);builder.Services.AddOpenApi();var app = builder.Build();if (app.Environment.IsDevelopment())
{app.MapScalarApiReference(); // scalar/v1app.MapOpenApi();
}app.MapGet("/", () => "Hello world!");app.Run();

运行应用程序时,您可以在终端节点访问 API 文档。

http://localhost:port/scalar/v1

如何将 Bearer 身份验证方案添加到 Scalar ?

  • 以下是 Bearer 身份验证的示例转换器:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;namespace WebApplication1.Transformers;public sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{private readonly string _authenticationSchemeName = "Bearer";public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken){var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();if (authenticationSchemes.Any(authScheme => authScheme.Name == _authenticationSchemeName)){// Add the security scheme at the document levelvar requirements = new Dictionary<string, OpenApiSecurityScheme>{[_authenticationSchemeName] = new OpenApiSecurityScheme{Type = SecuritySchemeType.Http,Scheme = _authenticationSchemeName.ToLower(), // "bearer" refers to the header name hereIn = ParameterLocation.Header,BearerFormat = "Json Web Token"}};document.Components ??= new OpenApiComponents();document.Components.SecuritySchemes = requirements;// Apply it as a requirement for all operationsforeach (var operation in document.Paths.Values.SelectMany(path => path.Operations)){operation.Value.Security.Add(new OpenApiSecurityRequirement{[new OpenApiSecurityScheme{Reference = new OpenApiReference{Id = _authenticationSchemeName,Type = ReferenceType.SecurityScheme}}] = Array.Empty<string>()});}}}
}
  • 用法示例:
builder.Services.AddOpenApi(opt =>
{opt.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});

使用 Scalar 的式例

创建 webapi 项目

此处我们使用 .NET CLI 创建 ASP.NET Core Web API 项目,操作步骤如下:

1、确保已安装 .NET SDK

  • 可以通过运行 dotnet --version 命令来检查是否已安装 .NET9 SDK
  • 如果未安装,可以从 .NET 官方网站 下载并安装。

.NET 官方网站 :

  • https://dotnet.microsoft.com/zh-cn/download
  • https://dotnet.microsoft.com/en-us/download

2、创建项目目录:

mkdir MyWebApi

3、创建 ASP.NET Core Web API 项目:

dotnet new webapi -n MyWebApi

4、导航到项目目录:

cd MyWebApi

5、运行项目:

dotnet run

通过上面操作,此时我们就准备好 asp.net core webapi 项目,名称为:MyWebApi

安装 nuget 包

使用 .net cli 安装 nuget 包文件,执行如下命令:

dotnet add package Microsoft.AspNetCore.OpenApi --version 9.0.0-rc.2.24474.3
dotnet add package Scalar.AspNetCore --version 1.2.23

添加文件夹目录

在项目中添加文件夹目录,命名为:Transformers,并在该目录中添加 BearerSecuritySchemeTransformer.cs 文件,该文件的作用是将 Bearer 身份验证方案添加到 Scalar 中,代码演示如签名环节说明。

修改 Program.cs 文件

此处使用 MiniAPI 模式,在 Program.cs 文件中代码改造如下:

using System.Text.Json.Serialization;
using Scalar.AspNetCore;
using WebApplication1.Transformers;var builder = WebApplication.CreateSlimBuilder(args);// 配置 HTTP JSON 选项,用于自定义 JSON 序列化行为。
builder.Services.ConfigureHttpJsonOptions(options =>
{// 在类型解析链中插入自定义的 JSON 序列化上下文。options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});// 启用 OpenAPI 文档支持,并配置 OpenAPI 文档。
//builder.Services.AddOpenApi();
builder.Services.AddOpenApi(opt =>
{// 添加一个文档转换器,用于处理特定的安全方案(例如: Bearer Token)。opt.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});var app = builder.Build();if (app.Environment.IsDevelopment())
{// 映射 OpenAPI 文档路由。app.MapOpenApi();//app.MapScalarApiReference(); // scalar/v1// 映射自定义的 API 文档路由,并使用 Fluent API 进行配置,例如:设置标题、主题、侧边栏等。app.MapScalarApiReference(options =>{options.WithTitle("My custom API").WithTheme(ScalarTheme.Mars).WithSidebar(true).WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient).WithPreferredScheme("ApiKey").WithApiKeyAuthentication(x => x.Token = "my-api-key");});
}// 定义示例数据,一个包含示例待办事项的数组
var sampleTodos = new Todo[] {new(1, "Walk the dog"),new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),new(4, "Clean the bathroom"),new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
};// 定义 API 路由
var todosApi = app.MapGroup("/todos"); // 创建一个路由组,前缀为 /todos。
todosApi.MapGet("/", () => sampleTodos); // 映射 GET 请求到根路径,返回所有待办事项。
// 映射 GET 请求到特定 ID 的路径,返回对应的待办事项,如果找不到则返回 404 Not Found。
todosApi.MapGet("/{id}", (int id) =>sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo? Results.Ok(todo): Results.NotFound());app.Run();// 定义一个记录类 Todo,包含 Id、Title、DueBy 和 IsComplete 属性。
public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);// 自定义的 JSON 序列化上下文
[JsonSerializable(typeof(Todo[]))] // 标记 AppJsonSerializerContext 类,使其支持 Todo 数组的 JSON 序列化。
internal partial class AppJsonSerializerContext : JsonSerializerContext
{// 定义一个部分类 AppJsonSerializerContext,继承自 JsonSerializerContext,用于自定义 JSON 序列化行为。
}

运行项目,浏览器输入地址:

  • 查看 todos 接口数据
http://localhost:5264/todos

todos

  • 查看 scalar 页面:
http://localhost:5264/scalar/v1

scalar/v1

  • /todos

/todos

点击 【test request】显示如下:

test request

点击【send】显示如下:

send

Scalar 的配置扩展

Scalar.AspNetCore 包中,IEndpointRouteBuilder 该方法有一个可选参数,可用于自定义 Scalar UI 的行为:MapScalarApiReference

#region 程序集 Scalar.AspNetCore, Version=1.2.23.0, Culture=neutral, PublicKeyToken=null
// C:\Users\Jeffrey\.nuget\packages\scalar.aspnetcore\1.2.23\lib\net9.0\Scalar.AspNetCore.dll
// Decompiled with ICSharpCode.Decompiler 8.1.1.7464
#endregionusing System;
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Generated;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;namespace Scalar.AspNetCore;//
// 摘要:
//     Extension methods for Microsoft.AspNetCore.Routing.IEndpointRouteBuilder to provide
//     required endpoints.
public static class ScalarEndpointRouteBuilderExtensions
{private const string DocumentName = "{documentName}";private const string StaticAssets = "ScalarStaticAssets";internal const string ScalarJavaScriptFile = "scalar.js";//// 摘要://     Maps the Scalar API reference endpoint.//// 参数://   endpoints://     Microsoft.AspNetCore.Routing.IEndpointRouteBuilder.public static IEndpointConventionBuilder MapScalarApiReference(this IEndpointRouteBuilder endpoints){return endpoints.MapScalarApiReference(delegate{});}//// 摘要://     Maps the Scalar API reference endpoint.//// 参数://   endpoints://     Microsoft.AspNetCore.Routing.IEndpointRouteBuilder.////   configureOptions://     An action to configure the Scalar options.public static IEndpointConventionBuilder MapScalarApiReference(this IEndpointRouteBuilder endpoints, Action<ScalarOptions> configureOptions){ScalarOptions options = endpoints.ServiceProvider.GetService<IOptions<ScalarOptions>>()?.Value ?? new ScalarOptions();configureOptions(options);if (!options.EndpointPathPrefix.Contains("{documentName}")){throw new ArgumentException("'EndpointPathPrefix' must define '{documentName}'.");}bool useLocalAssets = string.IsNullOrEmpty(options.CdnUrl);string standaloneResourceUrl = (useLocalAssets ? options.EndpointPathPrefix.Replace("{documentName}", "scalar.js") : options.CdnUrl);EmbeddedFileProvider fileProvider = new EmbeddedFileProvider(typeof(ScalarEndpointRouteBuilderExtensions).Assembly, "ScalarStaticAssets");FileExtensionContentTypeProvider fileExtensionContentTypeProvider = new FileExtensionContentTypeProvider();string configuration = JsonSerializer.Serialize(options.ToScalarConfiguration(), ScalaConfigurationSerializerContext.Default.ScalarConfiguration);return endpoints.MapGet0(options.EndpointPathPrefix, (Func<string, IResult>)delegate (string documentName){if (useLocalAssets){IFileInfo fileInfo = fileProvider.GetFileInfo(documentName);if (fileInfo.Exists){string contentType;string contentType2 = (fileExtensionContentTypeProvider.TryGetContentType(documentName, out contentType) ? contentType : "application/octet-stream");return Results.Stream(fileInfo.CreateReadStream(), contentType2, null, fileInfo.LastModified);}}string value = options.Title.Replace("{documentName}", documentName);string value2 = options.OpenApiRoutePattern.Replace("{documentName}", documentName);return Results.Content($"<!doctype html>\n<html>\n<head>\n    <title>{value}</title>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n</head>\n<body>\n    <script id=\"api-reference\" data-url=\"{value2}\"></script>\n    <script>\n    document.getElementById('api-reference').dataset.configuration = JSON.stringify({configuration})\n    </script>\n    <script src=\"{standaloneResourceUrl}\"></script>\n</body>\n</html>", "text/html");}).ExcludeFromDescription();}
}

MapScalarApiReference 方法,除了上面的式例中使用的 Fluent API 模式,还可以使用 Object initializer 方式:

// Object initializer
app.MapScalarApiReference(options =>
{options.Title = "My custom API";options.Theme = ScalarTheme.Mars;options.ShowSidebar = false;options.DefaultHttpClient = new(ScalarTarget.CSharp, ScalarClient.HttpClient);options.Authentication = new ScalarAuthenticationOptions{PreferredSecurityScheme = "ApiKey",ApiKey = new ApiKeyOptions{Token = "my-api-key"}};
});

有关更多可能的选项及其默认值,请查看 ScalarOptions.cs 类。

  • ScalarOptions.cs 类,https://github.com/scalar/scalar/blob/main/packages/scalar.aspnetcore/src/Scalar.AspNetCore/Options/ScalarOptions.cs

也可以使用 options 模式通过依赖注入来配置选项:

builder.Services.Configure<ScalarOptions>(options => options.Title = "My custom API");
// or
builder.Services.AddOptions<ScalarOptions>().BindConfiguration("Scalar");

注意:通过该方法设置的选项将优先于通过依赖关系注入设置的选项。MapScalarApiReference

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

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

相关文章

Python4

4. 更多控制流工具 除了刚介绍的 while 语句&#xff0c;Python 还用了一些别的。我们将在本章中遇到它们。 4.1. if 语句 if elif else if x<0: x 0 print(Negative changed to zero) elif x0: print( zero) else: print(More) 4.2. for 语句 Pyth…

【大模型理论篇】大模型压缩技术之注意力层剪枝以及与MLP层联合剪枝

1. 背景分析 本来打算写一篇关于大模型蒸馏的文章&#xff0c;但刚好看到近期发表的一篇讨论大模型压缩的文章【1】&#xff0c;是关于注意力机制冗余性的讨论&#xff0c;比较有意思&#xff0c;作者分析得出并不是所有的注意力都是必须的&#xff0c;可以通过对模型去除冗余的…

引爆品牌曝光:揭秘Facebook品牌知名度广告的成功秘诀

来源&#xff1a;CREATING SUCCESSFUL FACEBOOK BRAND AWARENESS 本文主要介绍如何创建成功的Facebook品牌知名度广告活动。 创建成功的Facebook品牌知名度广告活动 在当今以Facebook为驱动的社交媒体管理中&#xff0c;品牌需要通过以下共同因素来构建品牌知名度&#xff1a;…

【音视频 | ADPCM】音频编码ADPCM详细介绍及例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

【ArcGIS Pro实操第5期】全局及局部空间插值:GPI、LPI、IDW等

ArcGIS Pro实操第5期&#xff1a;全局及局部空间插值 ArcGIS Pro-用于空间插值的丰富工具箱实操&#xff1a;空间插值方法1&#xff1a;Trend Surface Model for Interpolation-以降水数据为例方法2&#xff1a;Kernel Density Estimation Method-以单位面积鹿的目击数为例方法…

spring-第十一章 注解开发

spring 文章目录 spring前言1.注解回顾1.1原理1.2springIOC注解扫描原理1.2.1解释1.2.2案例 2.声明bean的注解补充&#xff1a;Bean注解&#xff0c;管理三方包对象 3.spring注解的使用3.1加入aop依赖3.2配置文件中添加context命名空间3.3配置文件中指定要扫描的包3.4在Bean上使…

2024_SHCTF_week2_Crypto

pading 题目&#xff1a; from Crypto.Util.number import * import gmpy2 flag bSHCTF{********} assert len(flag) 39 p getPrime(512) q getPrime(512) n p * q e 0x3 pad ba_easy_problem c pow(bytes_to_long(flag pad),e,n) print(fn {n}) print(fc {c})思路…

视频编辑的创意工坊,使用视频剪辑软件将视频随机分割成两段并去声进行MP3音频和M3u8文件的生成,让视频制作更高效

面对海量的视频编辑任务&#xff0c;你是否曾感到手足无措&#xff0c;渴望一种既简单又高效的方式来处理它们&#xff1f;别担心&#xff0c;媒体梦工厂软件带着它的魔法棒来啦&#xff01;它就像一位技艺高超的视频巫师&#xff0c;能轻松帮你在线完成视频编辑任务&#xff0…

提示工程(Prompt Engineering)指南(入门篇)

一、什么是AIGC AIGC全称为 “Artificial Intelligence Generated Content”&#xff0c;即 “人工智能生成内容”。代表了一种由语言模型和聊天机器人等人工智能系统驱动的内容创作的突破性方法。与人类作者制作的传统内容不同&#xff0c;AIGC 是通过算法生成的&#xff0c;…

二十二、Python基础语法(模块)

模块(module)&#xff1a;在python中&#xff0c;每个代码文件就是一个模块&#xff0c;在模块中定义的变量、函数、类别人都可以直接使用&#xff0c;如果想要使用别人写好的模块&#xff0c;就必须先导入别人的模块&#xff0c;模块名须满足标识符规则&#xff08;由字母、数…

解密 Redis:如何通过 IO 多路复用征服高并发挑战!

文章目录 一、什么是 IO 多路复用&#xff1f;二、为什么 Redis 要使用 IO 多路复用&#xff1f;三、Redis 如何实现 IO 多路复用&#xff1f;四、IO 多路复用的核心机制&#xff1a;epoll五、IO 多路复用在 Redis 中的工作流程六、IO 多路复用的优点七、IO 多路复用使用中的注…

stm32 ISP 串口程序下载

硬件原理图&#xff1a; 下载是通过 uart1 。不同的芯片 &#xff0c; 下载的uart 是不一样的。 最终连接到了 PA9&#xff0c; PA10 驱动的安装&#xff1a; 这里的驱动我已经安装过了。 程序下载软件 flymcu 是免安装的。 需要注意的点就是这些。 下载实测&#xff1a;…

电脑连接海康相机并在PictureBox和HWindowControl中分别显示。

展示结果&#xff1a; 下面附上界面中所有控件的Name&#xff0c;只需照着红字设置对应的控件Name即可 下面附上小编主界面的全部代码&#xff1a; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; …

【算法练习】最小生成树

题意&#xff1a;【模板】最小生成树 方法1&#xff1a;Prim算法(稠密边用优&#xff09; #include <bits/stdc.h> using namespace std; int n,m,u,v,d,ans; bool f[5001]; vector<pair<int,int>> a[5001];//用结构体和重载比直接定义小根堆似乎还快一点点…

利用 Google AI 工具提升应用智能化:ML Kit、TensorFlowLite、Cloud Vision、AutoML、Gemini

在code应用开发中&#xff0c;机器学习和人工智能正逐渐成为提升用户体验和应用智能化的重要手段。Google 提供了多种强大的 AI 工具&#xff0c;可以帮助开发者快速集成各种机器学习功能。本文将详细介绍五个关键工具&#xff1a; Firebase ML Kit、TensorFlow Lite、Google …

kafka 的高可用机制是什么?

大家好&#xff0c;我是锋哥。今天分享关于【kafka 的高可用机制是什么&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; kafka 的高可用机制是什么&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Apache Kafka 是一个分布式消息系统&am…

Peach-9B-8k-Roleplay模型部署指南

一、模型介绍 Peach-9B-8k-Roleplay 是一种聊天大型语言模型&#xff0c;它是通过我们的数据合成方法创建的超过 100K 的对话中微调 01-ai/Yi-1.5-9B 模型而获得的。 也许是 34B 以下参数最好的 LLM。 二、部署过程 1、更新环境 apt update2、安装Miniconda wget https://…

标准日志插件项目【C/C++】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;项目日记_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;项目介…

二、Spring的执行流程

文章目录 1. spring的初始化过程1.1 ClassPathXmlApplicationContext的构造方法1.2 refresh方法&#xff08;核心流程&#xff09;1.2.1 prepareRefresh() 方法1.2.2 obtainFreshBeanFactory() 方法1.2.3 prepareBeanFactory() 方法1.2.4 invokeBeanFactoryPostProcessors() 方…

2024年9月电子学会Scratch图形化编程等级考试三级真题试卷

2024年9月Scratch图形化编程等级考试三级真题试卷 一、选择题 第 1 题 单选题 scratch运行下列程序后&#xff0c;变量“和”的取值范围是&#xff1f;&#xff08; &#xff09; A.0~12 B.0~11 C.2~11 D.2~12 第 2 题 单选题 默认角色小猫&#xff0c;scratch运行下列…