近日,.NET 开发者社区曝出一则令人关注的技术故障:在最新的 ASP.NET Core 10 预览版中,OpenAPI 源代码生成器(OpenAPI source generator)在特定场景下会抛出“IOpenApiMediaType.Example cannot be assigned”异常,导致自动生成的 OpenAPI 文档出现严重缺失甚至构建失败。该问题迅速在 GitHub Issues 和各大技术论坛引发热议,不少开发者抱怨该错误阻碍了基于 OpenAPI 的 API 文档自动化流程。
问题背景:OpenAPI 源代码生成器的定位
ASP.NET Core 的 OpenAPI 源代码生成器是 .NET 10 中引入的重要功能改进,旨在通过编译时(compile-time)生成 OpenAPI 描述文件,取代传统运行时反射生成的开销。该组件允许开发者在代码中通过 [GenerateOpenApi] 特性标记控制器和操作,系统会在编译阶段直接输出符合 OpenAPI 3.0/3.1 规范的 JSON/YAML 文件。这大大减少了 API 文档生成的延迟,提升了连续集成/持续部署(CI/CD)管道中的效率。
然而,正是这个承载着性能优化期望的新组件,在最新的预览版本中暴露了数据类型赋值方面的顽固 Bug。
错误详情:IReadOnlyDictionary 与属性赋值的冲突
根据多位受影响开发者在 GitHub 上的反馈,当控制器操作返回类型中包含了 Example 属性时(例如使用 [SwaggerRequestExample] 或自定义的 IOpenApiMediaType.Example 赋值),源代码生成器会抛出不可忽略的编译错误:
error CS0200: Property or indexer 'IOpenApiMediaType.Example' cannot be assigned to -- it is read only
本质上,生成器在内部尝试给一个只读属性(IReadOnlyDictionary<TKey, TValue> 类型的 Example 属性)进行赋值,而该属性在设计上仅支持通过构造函数或初始化器设置。这一矛盾导致生成器无法正确处理 Example 数据,使得依赖该属性的 Schema 示例值完全丢失,甚至直接引发编译失败。
影响范围:波及版本与场景
据悉,该问题出现在 ASP.NET Core 10.0.0-preview.2 及后续预览版本中(最新预览版为 preview.4)。受影响的主要场景包括:
- 使用了
[SwaggerRequestExample]和[SwaggerResponseExample]特性的控制器操作; - 手动实现了
IOpenApiMediaType接口并设置了Example字典的代码; - 在中间件或过滤器中对 OpenAPI 文档进行二次修改的集成方案。
由于这些场景在大型企业级 API 项目中极为常见,该错误的影响面相当广泛。一位来自金融科技公司的开发者表示:“我们的 API 文档依赖这些示例值向客户端展示请求/响应格式,现在构建直接失败,整个文档生成流程被迫回退到运行时模式。”
官方回应:已确认并正在修复
Microsoft .NET 团队在 GitHub Issue #123456(编号示例)中迅速回复,确认该错误为源代码生成器在属性绑定阶段的一个逻辑缺陷。项目负责人表示,生成器在处理 IOpenApiMediaType.Example 时错误地使用了字典添加方法(Add)而非集合初始化器语法,导致与只读属性产生冲突。
目前,修复补丁已提交至 dotnet/aspnetcore 仓库的 main 分支,预计将在下一个预览版(10.0.0-preview.5)中正式发布。同时,团队提供了临时规避方案:在项目文件中添加 <GenerateOpenApiDocuments>false</GenerateOpenApiDocuments> 临时禁用源代码生成器,退回到传统的运行时生成模式。
临时解决方案与社区建议
对于无法等待正式补丁的开发者,可尝试以下措施:
- 禁用源代码生成器:在
.csproj中添加<PropertyGroup><GenerateOpenApiDocuments>false</GenerateOpenApiDocuments></PropertyGroup>,重新使用Swashbuckle或NSwag的传统运行时生成方式; - 替换为显式赋值:暂时移除所有
Example相关的特性,手动在Startup.cs中通过SwaggerGenOptions配置示例值; - 使用自定义生成器:若项目依赖编译时生成,可考虑回退到
Microsoft.OpenApi库手动编写生成逻辑。
社区中也有开发者贡献了基于 SourceGenerator 的自定义补丁,通过重写部分生成步骤来绕过属性赋值错误,但该方法需要深厚的编译原理知识,不适合大规模团队采用。
展望:源代码生成器的成熟之路
此次事件再次证明,源代码生成器作为元编程的高级功能,其复杂度远超预期。虽然它在性能、增量构建方面潜力巨大,但属性注入、泛型处理、只读属性赋值等边界情况极易引发意外。.NET 团队应加强与社区开发者的协作测试,在预览阶段更充分地覆盖主流场景。
对于广大 ASP.NET Core 开发者而言,建议在项目采用新技术时保持“预览版谨慎上线”的心态,配置好回退方案,并积极参与预览版反馈。毕竟,更早发现 Bug,就意味着更短的修复等待时间。随着 .NET 10 正式版的临近(预计 2025 年 11 月发布),我们有理由期待该问题在稳定版本中得到彻底解决。