news 2026/4/16 3:20:37

使用Scalar.AspNetCore来管理你的OpenApi

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用Scalar.AspNetCore来管理你的OpenApi

一直觉得很好的一个组件,网上介绍少得可怜,没办法,只有自己爬官网了,又是对照git又是看doc文档,总算是玩明白了,现在完全抛弃那个谁谁谁了。因人喜好各取所长吧

先来官方参考地址:

https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/include-metadata?view=aspnetcore-9.0&tabs=minimal-apis

这是scalar的.net 集成文档地址

https://guides.scalar.com/scalar/scalar-api-references/integrations/net-aspnet-core/integration

github地址

https://github.com/scalar/scalar

先放个图,诱惑一下,集成了很多主题,还可以自定主题(留给前端去玩吧)

01

一、简单使用

1.建立一个API项目,(最小,mvc都可)

2.引用包

dotnet add package Scalar.AspNetCore (当前版本2.9.0)

dotnet add package Microsoft.AspNetCore.OpenApi(当前版本10.0)

3.添加引用

using Scalar.AspNetCore;

4.添加配置,在Program.cs中添加下面配置

复制代码

builder.Services.AddOpenApi();

if (app.Environment.IsDevelopment())

{

app.MapOpenApi();

app.MapScalarApiReference();

}

复制代码

现在运行一下,看看,localhost:xxxx/scalar

是不是看到列出漂亮的界面了?

二、基本配置

1.自定义路由

不想使用/salar,可以换成自己的地址

app.MapScalarApiReference("/api-docs");

app.MapScalarApiReference("/docs");

2.多文当或版本控制

复制代码

// Chain multiple documents

app.MapScalarApiReference(options =>

{

options.AddDocument("v1", "Production API", "api/v1/openapi.json")

.AddDocument("v2-beta", "Beta API", "api/v2-beta/openapi.json", isDefault: true)

.AddDocument("internal", "Internal API", "internal/openapi.json");

});

复制代码

isDefault: true是默认打开的页面

3.自定义文档的默认调试语言

app.MapScalarApiReference(options =>

{

options.WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);

});

02

它对应右边窗口的语言,基本上都支持,java,php,rust,py,swift

三、高级配置

之前的老版本使用的硬编码option加配置,2.9.0以后,在界面右上角菜单栏上出现了一个编辑配置功能

03

根据自己的喜好,调试编辑完配置文件后,可以复制到文件中单独保存,真是太贴心了

复制代码

{

"title": "Aquxa API Documentation",

"slug": "aquxa-api-documentation",

"hideClientButton": true,

"servers": [

{

"url": "http://localhost:5215",

"description": "Development server"

}

],

"showSidebar": true,

"showToolbar": "localhost",//这里特别说明一下,编辑完后,不想出现这个菜单栏,就在这里可以关闭showToolbar: "never"

"operationTitleSource": "summary",

"theme": "solarized",//主题可以自己选,喜欢哪个选哪个

"_integration": "dotnet",

"persistAuth": false,

"telemetry": true,

"layout": "modern",

"isEditable": false,

"isLoading": false,

"hideModels": true,

"documentDownloadType": "both",

"hideTestRequestButton": false,

"hideSearch": false,

"showOperationId": false,

"hideDarkModeToggle": false,

"favicon": "favicon.svg",

"withDefaultFonts": true,

"defaultOpenAllTags": false,

"expandAllModelSections": true,

"expandAllResponses": true,

"orderSchemaPropertiesBy": "alpha",

"orderRequiredPropertiesFirst": true,

"url": "http://localhost:5215/openapi/v1.json"

}

复制代码

PS:这里特别说明一下,编辑完后,不想出现这个菜单栏,就在这里可以关闭showToolbar: "never"

得到这个文件,保存到wwwroot/js/scalar-config.js,注意,一定要保存到能访问的静态目录里,并在program.cs添加静态目录的配置

app.UseStaticFiles(). //这个要放在scalar配置的前面,不然访问不到

添加配置文件加载

.WithJavaScriptConfiguration("/js/scalar-config.js")

04

这里费了好大的劲,查官方,看代码,因为官方文档还是老文档,只是简单的概括了一下。最后整出来了

四、文档的编辑

使用最重要的还是API文档编辑,其实它完全用的标准的OpenApi,只要参考这个表就可以完全配置了

05

复制代码

[ApiController]

[Route("api/[controller]")]

[ApiExplorerSettings(GroupName = "v1")]

[Tags("Admin")] // 为整个控制器添加标签

public class AdminController : ControllerBase

{

[HttpPost("reload-cache")]

public IActionResult ReloadCache()

{

// 模拟重新加载缓存的操作

return Ok("Cache reloaded successfully");

}

[HttpGet("stats")]

public IActionResult GetStats()

{

return Ok(new { Users = 100, Requests = 1000 });

}

}

复制代码

下面说一下常用的特性

1.API分组

[ApiExplorerSettings]

这个比较熟悉,它可以分组,分版本,当你分好版本后[ApiExplorerSettings(GroupName = "v1")]/[ApiExplorerSettings(GroupName = "v2")],会在scalar中左上角可以选择,当然,你也可以把它做为组来用

06

如果有不想显示的API也可以用[ApiExplorerSettings(IgnoreApi = true)]来排除显示

[HttpGet("/private")]

[ApiExplorerSettings(IgnoreApi = true)]

public IActionResult PrivateEndpoint() {

return Ok("This is a private endpoint");

}

2.API分类

[Tags]

分类的API,会归档在一起,方便查询,这样看起来没有那么乱了

复制代码

[Tags(["Admin", "OtherAPI"])]

[HttpGet("attributes")]

public IResult Attributes()

{

return Results.Ok("Hello world!");

}

复制代码

07

3.描述

复制代码

[EndpointSummary("OtherApi")]

[EndpointDescription("这是一个公开接口,无需认证")]

[HttpGet("attributes")]

public IResult Attributes()

{

return Results.Ok("Hello world!");

}

复制代码

08

4.过滤

不想显示的接口可以用

上面说的

[ApiExplorerSettings(IgnoreApi = true)]来关闭

还有一个就是根目录,如果在配置文件中有MapGet,可以使用.ExcludeFromDescription();排除显示

1

2

3

// 默认打开首页

app.MapGet("/", () => "Hangfire 服务运行中。访问 /hangfire 查看仪表盘,访问 /docs 查看API文档").ExcludeFromDescription();

//可以使用.ExcludeFromDescription();排除显示

更多编辑文档就看这里吧

https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/include-metadata?view=aspnetcore-9.0&tabs=controllers

五、认证授权

这里就使用自己的授权就可以,这里就偷懒找AI完成了。参考部分都有备注

复制代码

using Scalar.AspNetCore;

using Microsoft.AspNetCore.Authentication;

using Microsoft.Extensions.Options;

using System.Security.Claims;

using System.Text.Encodings.Web;

using Microsoft.AspNetCore.Mvc;

using MyWebApi; // 添加对WeatherForecast的引用

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi

builder.Services.AddOpenApi("v1");

builder.Services.AddOpenApi("v2");

// 添加控制器服务

builder.Services.AddControllers();

// 添加身份验证服务

builder.Services.AddAuthentication("BasicAuthentication")

.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);

// 添加授权服务

builder.Services.AddAuthorization(options =>

{

options.AddPolicy("ScalarAccess", policy => policy.RequireAuthenticatedUser());

});

// 配置服务器URL,避免端口冲突

builder.WebHost.UseUrls("http://localhost:5215");

var app = builder.Build();

// Configure static file middleware to serve the JavaScript config file

app.UseStaticFiles();

// 添加身份验证和授权中间件

app.UseAuthentication();

app.UseAuthorization();

// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())

{

app.MapOpenApi();

// Add Scalar for API management with JavaScript configuration and authorization

app.MapScalarApiReference("/scalar", options =>

{

options.WithTitle("MyWebApi")

.WithJavaScriptConfiguration("/js/scalar-config.js")

.AddDocument("v1", "Aquxa API Documentation",isDefault: true)

.AddDocument("v2", "Beta API");

})

.RequireAuthorization("ScalarAccess"); // 应用授权策略

}

// 添加控制器路由

app.MapControllers();

app.Run();

// Basic Authentication Handler

public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>

{

public BasicAuthenticationHandler(

IOptionsMonitor<AuthenticationSchemeOptions> options,

ILoggerFactory logger,

UrlEncoder encoder)

: base(options, logger, encoder)

{

}

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()

{

// 检查是否有Authorization头

if (!Request.Headers.ContainsKey("Authorization"))

return AuthenticateResult.NoResult();

try

{

// 解析Basic认证头

var authHeader = Request.Headers["Authorization"].ToString();

if (!authHeader.StartsWith("Basic "))

return AuthenticateResult.NoResult();

var encodedCredentials = authHeader.Substring("Basic ".Length).Trim();

var decodedCredentials = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(encodedCredentials));

var credentials = decodedCredentials.Split(':', 2);

var username = credentials[0];

var password = credentials[1];

// 验证用户名和密码(这里使用硬编码,实际应用中应从配置或数据库获取)

if (username == "admin" && password == "password123")

{

var claims = new[] { new Claim(ClaimTypes.Name, username) };

var identity = new ClaimsIdentity(claims, Scheme.Name);

var principal = new ClaimsPrincipal(identity);

var ticket = new AuthenticationTicket(principal, Scheme.Name);

return AuthenticateResult.Success(ticket);

}

return AuthenticateResult.Fail("Invalid username or password");

}

catch

{

return AuthenticateResult.Fail("Invalid Authorization Header");

}

}

protected override async Task HandleChallengeAsync(AuthenticationProperties properties)

{

// 发送WWW-Authenticate头以触发浏览器的认证对话框

Response.Headers["WWW-Authenticate"] = "Basic realm=\"Scalar API Documentation\"";

await base.HandleChallengeAsync(properties);

}

}

复制代码

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 18:07:12

3步搞定PictureSelector热修复:让Android图片选择器重获新生

3步搞定PictureSelector热修复&#xff1a;让Android图片选择器重获新生 【免费下载链接】PictureSelector Picture Selector Library for Android or 图片选择器 项目地址: https://gitcode.com/gh_mirrors/pict/PictureSelector 当您的Android应用中的图片选择器突然崩…

作者头像 李华
网站建设 2026/4/16 7:00:40

PS4游戏存档管理进阶指南:Apollo工具深度体验

PS4游戏存档管理进阶指南&#xff1a;Apollo工具深度体验 【免费下载链接】apollo-ps4 Apollo Save Tool (PS4) 项目地址: https://gitcode.com/gh_mirrors/ap/apollo-ps4 还在为PS4游戏存档的管理而烦恼吗&#xff1f;当珍贵的游戏进度需要备份&#xff0c;或者想要尝试…

作者头像 李华
网站建设 2026/4/16 12:13:13

阿里Wan2.2视频生成完整指南:如何在消费级显卡上实现电影级创作

想要用普通显卡就能生成专业级视频吗&#xff1f;阿里云通义万相团队开源的Wan2.2视频生成模型正是你需要的终极解决方案&#xff01;这款业界首个采用MoE&#xff08;混合专家&#xff09;架构的扩散模型&#xff0c;让720P高清视频生成在RTX 4090等消费级显卡上成为现实&…

作者头像 李华
网站建设 2026/4/16 12:59:10

VideoSrt:AI智能字幕生成工具全攻略

VideoSrt&#xff1a;AI智能字幕生成工具全攻略 【免费下载链接】video-srt-windows 这是一个可以识别视频语音自动生成字幕SRT文件的开源 Windows-GUI 软件工具。 项目地址: https://gitcode.com/gh_mirrors/vi/video-srt-windows 还在为视频字幕制作而烦恼吗&#xff…

作者头像 李华
网站建设 2026/4/16 0:38:28

SpringBoot3高效缓存:布隆过滤器实战

前言在当今互联网软件开发的高并发、海量数据场景下&#xff0c;如何高效处理数据、提升系统性能成为了开发者们持续关注的焦点。缓存作为提升系统性能的重要手段&#xff0c;在常规机制中却面临着缓存穿透的难题。当大量无效请求&#xff08;请求的 key 既不存在于缓存&#x…

作者头像 李华