
示例代码:https://download.csdn.net/download/hefeng_aspnet/90408075
介绍
随着 .NET 9 的发布,微软宣布他们将不再为任何 .NET API 项目提供默认的 Swagger gen UI。以前,当我们创建 .NET API 项目时,微软会自动添加 Swagger Swashbuckle 包,该包提供了app.UseSwagger()和app.UseSwaggerUI() 等方法。这些方法显示了带有预定义 UI 的 API 文档,可直接在浏览器中进行测试,而无需使用 Postman 等任何第三方应用程序。但是,Swagger 不再与 .NET 9 Web API 项目集成。做出此决定是因为该包最近没有得到妥善维护,并且许多用户报告的问题仍未解决。
微软团队创建了一个名为 Microsoft.AspNetCore.OpenApi 的新包,它提供了类似于 Swagger 的内置 OpenAPI 文档生成功能。但是,这只提供了所有端点和架构定义的 JSON 文档,而浏览器中不会显示任何 UI。这一变化的主要目的是让用户实现他们喜欢的 UI 库,无论是 Swagger 还是任何其他替代方案。微软删除默认的 Swagger 包并不意味着您不能在项目中再次安装 Swagger------您可以添加它并执行与以前相同的所有操作。
目前有许多 Swagger 的替代方案,但在本文中,我们将讨论并在我们的 API 项目中实现 Scalar。继 Swagger 之后,Scalar 在开发人员中越来越受欢迎。
创建新项目
当您使用 .NET 9 创建新项目时,它会询问您是否要配置 OpenAPI 支持。如果您选中此复选框,它会将 Microsoft.AspNetCore.OpenApi 包添加到您的项目中,并在 program.cs 文件中注册 OpenAPI 服务,如下所示:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}

现在,当您运行 API 并导航到/OpenApi/v1.json时,它将显示默认生成的文档,其中包含有关您的端点和您使用的所有模式的信息,如下图所示:

配置 Scalar.NET
首先,打开你的包管理器并安装Scalar.AspNetCore。

然后,只需在program.cs文件中添加app.MapScalarApiReference();即可映射 Scalar UI 的所有 API 引用和路由。
现在,如果您转到/Scalar/V1,您将看到端点的漂亮 UI。在这里,我只有一个端点,所以它看起来像这样。

配置标量的选项
您可以配置多个选项并更改 UI 的设置。一些配置包括。
1、Title:设置显示在浏览器选项卡顶部的文档标题
2、DarkMode: true/false 启用或禁用暗模式
3、Favicon:设置文档的图标
4、DefaultHttpClient:在浏览器中加载 UI 时显示默认 HTTP 客户端。它显示相应编程语言的代码实现。
5、HideModels: true/false 设置是否显示模型定义
6、Layout:设置 Scalar UI 的布局/主题
7、ShowSidebar: true/false 设定是否显示侧边栏。这仅在您选择了现代布局时才有效。
还有更多。
默认打开 Scalar UI
您可能已经注意到,我们每次都必须在 URL 中输入 scalar/v1 才能看到 Scalar UI。我们可以更改启动 URL,这样就不必重复执行此操作。打开launchsettings.json文件并将启动 URL 添加到您的配置文件中。我已为 HTTP 和 HTTPS 添加了它。您可以根据您的要求进行配置。

使用授权和 JWT 令牌
在大多数 API 中,我们都会实现 JWT 令牌或其他类型的令牌身份验证。因此,我添加了几行代码来使用 JWT 令牌实现授权。我还为此安装了 Microsoft.AspNetCore.Authentication.JwtBearer 包。
builder.Services
.AddAuthorization()
.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("your_jwt_key")),
ValidateIssuer = false,
ValidateAudience = false
};
});
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/test1", () => "This is test 1 endpoint")
.WithName("Test1")
.RequireAuthorization();
当我调用此 test1 端点时,它给出了401 错误(未经授权)。那么,我们如何解决这个问题呢?我们可以简单地传递一个身份验证令牌,但如果你看看 Scalar,你会发现没有选项可以在他们的 UI 上添加身份验证/承载令牌。即使我在MapScalarApiReference中添加了PreferredSecurityScheme作为承载者,也没有针对身份验证类型的选项。
options.Authentication = new ScalarAuthenticationOptions
{
PreferredSecurityScheme = "Bearer"
};

如果您在标头中将身份验证令牌与授权密钥一起传递,则它可以工作,但这不是我们想要的,对吗?我们想要一个类似于 Swagger 的界面,它显示在主页或各个端点上添加令牌的选项。这是 Scalar 的一个问题,已在其 GitHub 存储库中报告:https://github.com/scalar/scalar/issues/4055。

但是,有一种方法可以实现我们想要的并解决这个问题。我们可以使用 OpenAPI 中的文档转换器功能,微软在这里提供了详细的文档:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/customize-openapi ?view=aspnetcore-9.0 。
使用这个转换器,我们可以通知 Scalar 我们想要在 UI 上显示身份验证选项,以便 Scalar 可以将其添加到主页以及各个端点上。
这是压缩类:
internal sealed class BearerSecuritySchemeTransformer : IOpenApiDocumentTransformer
{
private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;
public BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider)
{
_authenticationSchemeProvider = authenticationSchemeProvider;
}
public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
var authenticationSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
{
var requirements = new Dictionary<string, OpenApiSecurityScheme>
{
"Bearer"\] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
In = ParameterLocation.Header,
BearerFormat = "JWT"
}
};
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 = "Bearer",
Type = ReferenceType.SecurityScheme
}
}\] = Array.Empty\