news 2026/3/17 5:09:11

使用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/3/5 2:39:33

Nacos 面试题及答案整理,最新面试题

Nacos的核心功能有哪些&#xff1f; Nacos的核心功能主要包括以下几点&#xff1a; 1、服务发现与注册&#xff1a; Nacos支持服务的注册与发现&#xff0c;允许服务实例在Nacos中注册&#xff0c;并被客户端发现和调用。 2、配置管理&#xff1a; 提供动态的配置服务&#…

作者头像 李华
网站建设 2026/3/7 0:03:09

2026年河北省职业院校技能大赛“区块链技术应用”竞赛样题

2026年河北省职业院校技能大赛“区块链技术应用”竞赛样题 文章目录2026年河北省职业院校技能大赛“区块链技术应用”竞赛样题模块一&#xff1a;区块链产品方案设计及系统运维任务1-1&#xff1a;区块链产品需求分析与方案设计任务1-2&#xff1a;区块链系统部署与运维任务1-3…

作者头像 李华
网站建设 2026/3/15 15:13:54

PyBlueZ完整指南:Python蓝牙编程从入门到精通

PyBlueZ完整指南&#xff1a;Python蓝牙编程从入门到精通 【免费下载链接】pybluez Bluetooth Python extension module 项目地址: https://gitcode.com/gh_mirrors/py/pybluez PyBlueZ作为Python蓝牙编程的重要工具&#xff0c;为开发者提供了强大的蓝牙通信能力。这个…

作者头像 李华
网站建设 2026/3/13 14:13:44

2025降噪耳机排行榜前十名:漫步者领衔,国产耳机以高性价比破局

科技与性价比的完美结合&#xff0c;让降噪耳机从高端奢侈品成为了大众日常工具。无论是在嘈杂的地铁上、喧闹的办公室中&#xff0c;还是长途飞行的旅程中&#xff0c;一款优秀的降噪耳机都能为你创造一片宁静的听觉空间。2025年&#xff0c;中国耳机品牌凭借卓越的技术实力和…

作者头像 李华
网站建设 2026/3/13 4:09:56

GLM-4.5开源大模型:智能体开发的新时代引擎

GLM-4.5开源大模型&#xff1a;智能体开发的新时代引擎 【免费下载链接】GLM-4.5-Air-Base 项目地址: https://ai.gitcode.com/zai-org/GLM-4.5-Air-Base 在人工智能技术飞速发展的今天&#xff0c;智谱AI正式推出GLM-4.5系列开源大模型&#xff0c;这款专为智能体应用…

作者头像 李华