关于 dotnet-api-docs
面向 .NET 项目的 API 文档生成技能,涵盖 DocFX 参考文档与 OpenAPI 交互式文档,并提供同步校验和版本维护实践。
主要功能
- 01从程序集生成 DocFX API 参考
- 02定制模板与页面交叉引用
- 03嵌入 Scalar 或 Swagger UI
- 04校验文档完整性与链接
- 05维护版本文档和迁移指南
适用场景
- 01为 .NET 库构建 API 参考站点
- 02将 OpenAPI 规范呈现为交互文档
- 03在 CI 中发现缺失注释和断链
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-api-docs安装后在 Claude Code 中输入/dotnet-api-docs确认已加载。
详细介绍
dotnet-api-docs
为 .NET 项目生成 API 文档:配置 DocFX,从程序集生成 API 参考(docfx.json 配置、元数据提取、模板自定义、交叉引用),将 OpenAPI 规范用作实时 API 文档(嵌入 Scalar 和 Swagger UI、版本化 OpenAPI 文档),同步文档与代码(通过 -warnaserror:CS1591 在 CI 中验证、检测失效链接、在 PR 上自动构建文档),API 更新日志模式(记录重大变更、迁移指南、跟踪已弃用的 API),以及版本化 API 文档(版本选择器、多版本维护、URL 模式)。
版本假设: DocFX v2.x(由社区维护)。通过 Microsoft.AspNetCore.OpenApi 使用 OpenAPI 3.x(.NET 9+ 内置)。使用 Scalar UI 展示现代 OpenAPI。代码示例以 .NET 8.0+ 为基准。
范围边界: 此技能负责从代码生成 API 文档,包括将源代码、XML 注释和 OpenAPI 规范转换为可浏览文档的工具和流程。XML 文档注释语法和编写规范由 [skill:dotnet-xml-docs] 负责。OpenAPI 规范生成和 Swashbuckle 迁移由 [skill:dotnet-openapi] 负责。文档站点的 CI/CD 部署由 [skill:dotnet-gha-deploy] 负责。文档平台的选择(Starlight、DocFX 或 Docusaurus)由 [skill:dotnet-documentation-strategy] 负责。
范围之外: XML 文档注释语法和编写——参见 [skill:dotnet-xml-docs]。OpenAPI 规范生成和配置(Swashbuckle、Microsoft.AspNetCore.OpenApi 设置)——参见 [skill:dotnet-openapi]。文档站点的 CI/CD 部署流水线——参见 [skill:dotnet-gha-deploy]。文档平台选择和初始设置——参见 [skill:dotnet-documentation-strategy]。更新日志生成工具和 SemVer 版本管理——参见 [skill:dotnet-release-management]。
交叉引用:[skill:dotnet-xml-docs](XML 文档注释编写)、[skill:dotnet-openapi](OpenAPI 生成)、[skill:dotnet-gha-deploy](文档站点部署流水线)、[skill:dotnet-documentation-strategy](平台选择)、[skill:dotnet-release-management](更新日志工具和版本管理)。
为 .NET API 参考配置 DocFX
DocFX 直接从 .NET 程序集和 XML 文档注释生成 API 参考文档。它是唯一支持从 .NET 项目原生运行 docfx metadata 提取元数据的文档工具。
安装
# Install DocFX as a .NET global tool
dotnet tool install -g docfx
# Or as a local tool (recommended for team consistency)
dotnet new tool-manifest
dotnet tool install docfx
配置(docfx.json)
{
"metadata": [
{
"src": [
{
"files": ["src/**/*.csproj"],
"exclude": ["**/bin/**", "**/obj/**"],
"src": ".."
}
],
"dest": "api",
"properties": {
"TargetFramework": "net8.0"
},
"disableGitFeatures": false,
"disableDefaultFilter": false
}
],
"build": {
"content": [
{
"files": ["api/**.yml", "api/index.md"]
},
{
"files": [
"articles/**.md",
"articles/**/toc.yml",
"toc.yml",
"*.md"
]
}
],
"resource": [
{
"files": ["images/**"]
}
],
"dest": "_site",
"globalMetadataFiles": [],
"fileMetadataFiles": [],
"template": ["default", "modern"],
"postProcessors": ["ExtractSearchIndex"],
"markdownEngineName": "markdig",
"noLangKeyword": false,
"keepFileLink": false,
"cleanupCacheHistory": false,
"disableGitFeatures": false,
"globalMetadata": {
"_appTitle": "My.Library API Reference",
"_appFooter": "Copyright 2024 My Company",
"_enableSearch": true,
"_enableNewTab": true
}
}
}
元数据提取
metadata 部分控制 DocFX 如何从 .NET 项目中提取 API 信息:
# Generate API metadata YAML files from projects
docfx metadata docfx.json
# This creates YAML files in the api/ directory:
# api/MyLibrary.WidgetService.yml
# api/MyLibrary.Widget.yml
# api/toc.yml
主要元数据配置选项:
| 属性 | 用途 | 默认值 |
|---|---|---|
src.files | 要从中提取的项目文件 | 必填 |
dest | YAML 输出目录 | api |
properties.TargetFramework | 要针对其进行构建的 TFM | 项目默认值 |
disableGitFeatures | 跳过 Git blame 信息 | false |
filter | API 筛选 YAML 文件的路径 | 无(所有公共 API) |
API 筛选
从生成的文档中排除内部类型:
# filterConfig.yml
apiRules:
- exclude:
uidRegex: ^MyLibrary\.Internal\.
type: Namespace
- exclude:
hasAttribute:
uid: System.ComponentModel.EditorBrowsableAttribute
ctorArguments:
- System.ComponentModel.EditorBrowsableState.Never
在 docfx.json 中引用筛选文件:
{
"metadata": [
{
"filter": "filterConfig.yml"
}
]
}
自定义模板
DocFX 支持通过覆盖模板自定义品牌样式:
docs/
templates/
custom/
styles/
main.css # Custom CSS overrides
partials/
head.tmpl.partial # Custom head section (analytics, fonts)
footer.tmpl.partial
在 docfx.json 中引用自定义模板:
{
"build": {
"template": ["default", "modern", "templates/custom"]
}
}
页面间交叉引用
DocFX 支持在 API 页面和概念性文章之间使用基于 uid 的交叉引用:
See the @MyLibrary.WidgetService.CreateWidgetAsync(System.String) method for details.
For the full API, see <xref:MyLibrary.WidgetService>.
# In an API YAML override file (api/MyLibrary.WidgetService.yml)
# Add links to conceptual articles
references:
- uid: MyLibrary.WidgetService
seealso:
- linkId: ../articles/getting-started.md
commentId: getting-started
将 OpenAPI 规范用作文档
生成的 OpenAPI 规范可作为与代码保持同步的实时 API 文档。本节介绍如何将 OpenAPI 输出用作文档;有关 OpenAPI 的生成和配置,请参见 [skill:dotnet-openapi]。
Scalar UI 嵌入
Scalar 提供现代化的交互式 API 文档查看器:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi(); // Serves OpenAPI JSON at /openapi/v1.json
app.MapScalarApiReference(options =>
{
options.WithTitle("My API Documentation")
.WithTheme(ScalarTheme.Purple)
.WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
});
}
app.Run();
Scalar 会将 OpenAPI 规范呈现为交互式文档页面,其中包含:
- 按标签对端点分组
- 请求/响应示例
- 身份验证配置
- 用于测试端点的“试用”功能
Swagger UI 嵌入
对于使用 Swashbuckle 或需要经典 Swagger UI 的项目:
if (app.Environment.IsDevelopment())
{
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/openapi/v1.json", "My API v1");
options.RoutePrefix = "api-docs";
options.DocumentTitle = "My API Documentation";
options.DefaultModelsExpandDepth(-1); // Hide schemas by default
});
}
版本化 OpenAPI 文档
为不同的 API 版本提供多个 OpenAPI 文档:
builder.Services.AddOpenApi("v1", options =>
{
options.AddDocumentTransformer((document, context, ct) =>
{
document.Info.Version = "1.0";
document.Info.Title = "My API";
return Task.CompletedTask;
});
});
builder.Services.AddOpenApi("v2", options =>
{
options.AddDocumentTransformer((document, context, ct) =>
{
document.Info.Version = "2.0";
document.Info.Title = "My API";
return Task.CompletedTask;
});
});
// Serves /openapi/v1.json and /openapi/v2.json
app.MapOpenApi();
导出 OpenAPI 以生成静态文档
在构建时导出 OpenAPI 规范,以便用于静态文档站点:
# Generate OpenAPI spec from the running application
dotnet run -- --urls "http://localhost:5099" &
APP_PID=$!
sleep 3
curl -s http://localhost:5099/openapi/v1.json > docs/openapi/v1.json
kill $APP_PID
或者,使用 Microsoft.Extensions.ApiDescription.Server 包在构建时生成:
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PropertyGroup>
<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
<OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)/../docs/openapi</OpenApiDocumentsDirectory>
</PropertyGroup>
有关 OpenAPI 生成设置和 Swashbuckle 迁移详情,请参阅 [skill:dotnet-openapi]。
从 XML 注释生成文档站点
XML 文档转 DocFX(静态 HTML)
用于库 API 参考文档的主要工作流:
Source Code (.cs files)
|
v
XML Doc Comments (/// <summary>...)
|
v
Build with GenerateDocumentationFile=true
|
v
XML Doc File (MyLibrary.xml)
|
v
docfx metadata (extracts API structure)
|
v
YAML Files (api/*.yml)
|
v
docfx build (generates HTML)
|
v
Static HTML Site (_site/)
有关 XML 文档注释编写的最佳实践,请参阅 [skill:dotnet-xml-docs]。
XML 文档转 Starlight(通过 Markdown 提取)
对于使用 Starlight 而非 DocFX 的项目,可将 API 文档提取为 Markdown:
- 生成 XML 文档文件,方法是设置
<GenerateDocumentationFile>true</GenerateDocumentationFile> - 使用转换工具将 XML 文档转换为 Markdown 页面:
xmldoc2md(社区工具):将 XML 文档文件转换为 Markdown- 自定义脚本:解析 XML 文件,并为每种类型生成 Markdown 页面
# Using xmldoc2md
dotnet tool install -g XMLDoc2Markdown
xmldoc2md MyLibrary.dll docs/src/content/docs/reference/
# Output: one Markdown file per type in the reference/ directory
- 纳入 Starlight 构建:
docs/src/content/docs/
reference/
MyLibrary.WidgetService.md # Auto-generated from XML docs
MyLibrary.Widget.md
MyLibrary.WidgetStatus.md
配置侧边栏,使其从参考文档目录自动生成:
// astro.config.mjs
sidebar: [
{
label: 'API Reference',
autogenerate: { directory: 'reference' },
},
],
保持文档与代码同步
在 CI 中验证文档完整性
在 CI 中将 CS1591 视为错误,以强制确保 XML 文档完整:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(IsPublicLibrary)' == 'true'">
<WarningsAsErrors>$(WarningsAsErrors);CS1591</WarningsAsErrors>
</PropertyGroup>
# CI command: build with warnings-as-errors for doc completeness
dotnet build -warnaserror:CS1591
如果任何公共成员缺少 XML 文档,这会导致构建失败。使用 IsPublicLibrary 条件(或按项目配置),仅将此规则应用于已发布的 NuGet 包,而不应用于测试项目或内部工具。
检测失效链接
在 CI 中验证文档链接:
# Build DocFX and check for broken cross-references
docfx build docfx.json --warningsAsErrors
# DocFX reports broken xref links as warnings -- the flag promotes them to errors
对于 Starlight 或 Docusaurus 站点,可在构建后使用链接检查器:
# Build the doc site
npm run build
# Check for broken links in the built output
npx broken-link-checker-local ./_site --recursive
在 PR 中自动构建文档
在每个拉取请求中验证文档构建,但不进行部署。有关部署工作流配置,请参阅 [skill:dotnet-gha-deploy]。验证步骤通常作为 CI 工作流的一部分运行:
# In CI: verify docs build without errors
dotnet build -warnaserror:CS1591 # XML doc completeness
docfx metadata docfx.json # API metadata extraction
docfx build docfx.json --warningsAsErrors # Full doc site build
这样可以在文档问题(文档缺失、交叉引用失效)进入主分支之前,发现文档回归。
API 更新日志模式
记录重大变更
使用结构化格式记录重大变更,方便使用者快速浏览:
## Breaking Changes in v3.0
### Removed APIs
| API | Replacement | Migration |
|-----|-------------|-----------|
| `WidgetService.Create(string)` | `WidgetService.CreateAsync(string, CancellationToken)` | Add `await` and `CancellationToken` parameter |
| `Widget.Name` setter | `WidgetService.RenameAsync(Guid, string)` | Use service method instead of direct property mutation |
| `IWidgetRepository` (interface) | `IWidgetRepository<T>` (generic) | Update implementations to use generic interface |
### Changed Behavior
- `WidgetService.CreateAsync` now validates name uniqueness within a category.
Previously, duplicate names were silently allowed.
- `Widget.Status` defaults to `Draft` instead of `Active`.
Existing code that assumes newly created widgets are active must call `widget.Activate()`.
### New Required Dependencies
- `Microsoft.Extensions.Caching.Memory` is now a required dependency for `WidgetService`.
Register with `builder.Services.AddMemoryCache()`.
主要版本之间的迁移指南
按所需执行的操作组织迁移指南:
# Migrating from v2.x to v3.0
## Step 1: Update Package References
```xml
<PackageReference Include="My.Library" Version="2.*" />
<PackageReference Include="My.Library" Version="3.0.0" />
步骤 2:修复编译错误
异步 API 变更
所有同步方法均已移除。请将同步调用替换为对应的异步调用:
// Before (v2.x)
var widget = service.Create("name");
// After (v3.0)
var widget = await service.CreateAsync("name", cancellationToken);
泛型仓储接口
// Before (v2.x)
public class MyRepo : IWidgetRepository { }
// After (v3.0)
public class MyRepo : IWidgetRepository<Widget> { }
步骤 3:更新行为假设
- 检查所有假定创建后
Widget.Status == Active的代码路径 - 将
builder.Services.AddMemoryCache()添加到 DI 注册中
### Deprecated API Tracking
Use the `[Obsolete]` attribute with message pointing to the replacement. Document deprecation timelines:
```csharp
/// <summary>
/// Creates a widget synchronously.
/// </summary>
/// <remarks>
/// This method will be removed in v4.0. Use
/// <see cref="CreateAsync(string, CancellationToken)"/> instead.
/// </remarks>
[Obsolete("Use CreateAsync instead. This method will be removed in v4.0.", error: false)]
public Widget Create(string name)
{
}
在专门的文档中跟踪已弃用的 API:
# Deprecated APIs
| API | Deprecated In | Removed In | Replacement |
|-----|---------------|------------|-------------|
| `WidgetService.Create(string)` | v2.5 | v4.0 (planned) | `CreateAsync(string, CancellationToken)` |
| `Widget.Name` setter | v3.0 | v4.0 (planned) | `WidgetService.RenameAsync(Guid, string)` |
| `WidgetOptions.EnableCache` | v3.1 | v5.0 (planned) | `WidgetOptions.CachePolicy` |
有关更新日志格式约定和 SemVer 版本控制策略,请参阅 [skill:dotnet-release-management]。
版本化 API 文档
文档站点中的版本选择器
DocFX 版本化文档:
DocFX 支持通过指定不同的项目版本来提取特定版本的元数据:
{
"metadata": [
{
"src": [{ "files": ["src/**/*.csproj"], "src": ".." }],
"dest": "api/v2",
"properties": { "TargetFramework": "net8.0" },
"globalNamespaceId": "v2"
}
]
}
为每个主版本维护单独的分支或标签,并从各自的分支或标签构建文档:
# Build docs for v2.x (current branch)
docfx build docfx.json
# Build docs for v1.x (from tag)
git checkout v1.x
docfx build docfx.json --output _site/v1
git checkout main
Starlight 版本化文档:
使用基于目录的版本管理,或使用 @lorenzo_lewis/starlight-utils 插件。有关 Starlight 版本管理的设置,请参阅 [skill:dotnet-documentation-strategy]。
Docusaurus 版本化文档:
Docusaurus 内置了版本管理功能,可使用 npx docusaurus docs:version。有关 Docusaurus 版本管理的设置,请参阅 [skill:dotnet-documentation-strategy]。
维护多个活跃版本的文档
同时支持多个活跃的主版本时:
- 每个主版本使用一个分支的策略: 在主分支上维护
docs/v1、docs/v2目录,或使用单独的v1.x、v2.x分支 - 共享概念性文档: 将与版本无关的指南(架构、概念)放在共享位置,并将特定版本的 API 参考放在单独的目录中
- 版本横幅: 在旧版本文档中添加通知横幅,指向最新版本
URL 模式
版本化 API 文档的一致 URL 模式:
https://docs.mylib.dev/ # Latest stable version
https://docs.mylib.dev/v2/ # Specific version
https://docs.mylib.dev/v2/api/WidgetService # Specific type in specific version
https://docs.mylib.dev/latest/ # Alias for latest stable
https://docs.mylib.dev/next/ # Pre-release / unreleased docs
配置重定向,使不带版本号的 URL 指向最新的稳定版本。这样可确保发布新版本时,现有链接仍然有效。
Agent 常见注意事项
-
不要生成 OpenAPI 规范配置——OpenAPI 生成设置(
builder.Services.AddOpenApi()、文档转换器、Swashbuckle 迁移)属于 [skill:dotnet-openapi]。本技能涵盖如何将生成的 OpenAPI 输出用作文档。 -
不要编写 XML 文档注释语法指南——XML 标签语法、约定、
<inheritdoc>和GenerateDocumentationFile属于 [skill:dotnet-xml-docs]。本技能涵盖从 XML 文档到生成的文档站点的流程。 -
不要生成 CI 部署 YAML——文档站点部署工作流(GitHub Pages 操作、DocFX 部署)属于 [skill:dotnet-gha-deploy]。本技能涵盖文档构建验证和本地生成。
-
docfx metadata需要可构建的项目——项目必须成功编译,DocFX 才能提取 API 元数据。在 CI 流水线中,始终先运行dotnet build,再运行docfx metadata。 -
自 2022 年 11 月起,DocFX 由社区维护——Microsoft 已移交该代码库。它仍在积极维护,并得到广泛使用。对于正在评估替代方案的新项目,请参阅 [skill:dotnet-documentation-strategy]。
-
DocFX 的
modern模板需要 v2.75+——更早的版本使用default模板,该模板不支持 Mermaid,也没有现代样式。使用docfx --version检查已安装的版本。 -
-warnaserror:CS1591应仅应用于公共库项目——将它应用于测试项目、控制台应用或内部工具会造成不必要的文档负担。使用 MSBuild 条件,仅针对已发布的包。 -
使用
filterConfig.yml筛选 API 时,应使用 UID 正则表达式,而非命名空间字符串——模式^MyLibrary\.Internal\.匹配以该前缀开头的 UID。使用docfx metadata --log verbose测试筛选模式,以验证筛选是否正确。 -
破坏性变更文档必须包含迁移代码示例——只列出已移除 API、却不展示替代代码的表格是不够的。始终包含变更前后的代码片段。
-
版本化文档 URL 必须将不带版本号的路径重定向到最新稳定版本——发布新版本时,不要破坏现有链接。在根 URL 配置服务器端重定向,或添加客户端重定向页面。
-
OpenAPI UI(Scalar、Swagger UI)应仅在开发环境中公开——将
MapScalarApiReference和UseSwaggerUI放在if (app.Environment.IsDevelopment())条件中。生产环境公开交互式 API 文档涉及安全问题。