.NET 8 Web API如何自定义Swagger的XDocument请求示例值?
问题描述
我用.NET 8编写了一个C# Web API的Post接口,代码如下:
[Route("/v1.0/Test/TestXmlCall")] [Consumes("application/xml")] [HttpPost] public async Task<IResult> TestXmlCall([FromBody][SwaggerTryItOutDefaultValue("<Test></Test>")] XDocument xml) { var requestType = APIRequestType.ReportTable2; var acerTableType = AcerTableType.Table2; return await ReportNonStandardTrade(requestType, acerTableType); }
接口能正常运行,但Swagger中显示的示例值是XDocument的完整结构描述,不是我预期的<Test></Test>。我尝试自定义了SwaggerTryItOutDefaultValue特性和对应的ISchemaFilter,代码如下:
public class SwaggerTryItOutDefaultValue : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (context.ParameterInfo != null) { var att = context.ParameterInfo.GetCustomAttribute<SwaggerTryItOutDefaultValueAttribute>(); if (att != null) { schema.Example = new Microsoft.OpenApi.Any.OpenApiString(att.Value.ToString()); } } } } public class SwaggerTryItOutDefaultValueAttribute : Attribute { public string Value { get; } public SwaggerTryItOutDefaultValueAttribute(string value) { Value = value; } }
但这种方式并未成功修改Swagger中的示例值,请问有没有可行的解决方法?
解决方案
方法1:调整SchemaFilter逻辑,适配XDocument类型
现有SchemaFilter失效的原因大概率是context.ParameterInfo在处理FromBody参数时无法正确获取,或者Swashbuckle对XDocument的Schema生成有特殊逻辑。可以修改SchemaFilter,直接清理默认生成的属性并指定示例:
public class SwaggerTryItOutDefaultValue : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { // 从参数上获取自定义特性 var paramAttribute = context.ParameterInfo?.GetCustomAttribute<SwaggerTryItOutDefaultValueAttribute>(); if (paramAttribute != null) { // 清除XDocument默认生成的复杂属性 schema.Properties.Clear(); // 指定类型为字符串、格式为XML schema.Type = "string"; schema.Format = "xml"; // 设置示例值 schema.Example = new OpenApiString(paramAttribute.Value); return; } // 兼容类型上的特性(如果后续用到模型类) var typeAttribute = context.Type.GetCustomAttribute<SwaggerTryItOutDefaultValueAttribute>(); if (typeAttribute != null) { schema.Properties.Clear(); schema.Type = "string"; schema.Format = "xml"; schema.Example = new OpenApiString(typeAttribute.Value); } } }
记得在Program.cs中注册这个Filter:
builder.Services.AddSwaggerGen(c => { c.SchemaFilter<SwaggerTryItOutDefaultValue>(); });
方法2:用IDocumentFilter直接修改目标接口的请求示例
如果SchemaFilter还是不生效,可以直接定位到目标接口,修改它的请求示例配置:
public class XmlExampleDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { // 找到目标接口的路径 if (swaggerDoc.Paths.TryGetValue("/v1.0/Test/TestXmlCall", out var pathItem) && pathItem.Post != null) { var requestBody = pathItem.Post.RequestBody; if (requestBody != null && requestBody.Content.TryGetValue("application/xml", out var mediaType)) { // 设置XML示例值 mediaType.Example = new OpenApiString("<Test></Test>"); // 调整Schema为字符串类型,避免显示XDocument结构 mediaType.Schema.Type = "string"; mediaType.Schema.Format = "xml"; mediaType.Schema.Properties.Clear(); } } } }
注册这个DocumentFilter:
builder.Services.AddSwaggerGen(c => { c.DocumentFilter<XmlExampleDocumentFilter>(); });
方法3:改用强类型模型替代XDocument(推荐)
如果业务允许,定义强类型的XML模型,不仅能让Swagger自动生成更友好的示例,还能获得类型安全的好处。可以配合Swashbuckle.AspNetCore.Filters包自定义示例:
- 先安装包:
Install-Package Swashbuckle.AspNetCore.Filters
- 定义XML模型和示例提供类:
[XmlRoot("Test")] [Example(typeof(TestModelExample))] public class TestModel { // 根据实际需求添加XML属性或元素 } public class TestModelExample : IExamplesProvider<TestModel> { public TestModel GetExamples() { // 返回构造好的示例对象,Swagger会自动序列化为XML return new TestModel(); } }
- 修改接口参数:
[Route("/v1.0/Test/TestXmlCall")] [Consumes("application/xml")] [HttpPost] public async Task<IResult> TestXmlCall([FromBody] TestModel xml) { // 将强类型模型转换为XDocument处理 var xDoc = new XDocument(); using var writer = XmlWriter.Create(xDoc.CreateWriter()); new XmlSerializer(typeof(TestModel)).Serialize(writer, xml); var requestType = APIRequestType.ReportTable2; var acerTableType = AcerTableType.Table2; return await ReportNonStandardTrade(requestType, acerTableType); }
- 注册示例Filter:
builder.Services.AddSwaggerGen(c => { c.ExampleFilters(); });
内容的提问来源于stack exchange,提问作者Nick Tucker
相关产品推荐
相关产品推荐

