我有一个ASP.NET CoreWebAPI6.0项目,该项目包含一个端点,它的POST正文(application/ XML )中需要xml。我创建了一个属性如下:
using System;
/// <summary>
/// Used to mark an API for Swagger as having a raw XML body (Swagger creates an inout field).
/// </summary>
public class XmlPayloadAttribute : Attribute
{
/// <summary>
///
/// </summary>
public XmlPayloadAttribute()
{
ParameterName = "payload";
Required = true;
MediaType = "application/xml";
Format = "xml";
}
/// <summary>
///
/// </summary>
public string Format { get; set; }
/// <summary>
///
/// </summary>
public string MediaType { get; set; }
/// <summary>
///
/// </summary>
public bool Required { get; set; }
/// <summary>
///
/// </summary>
public string ParameterName { get; set; }
}...and a过滤器如下所示:
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen; // Swashbuckle.AspNetCore version 6.2.3
public class XmlPayloadFilter : IOperationFilter
{
/// <summary>
///
/// </summary>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var attribute = context.MethodInfo.GetCustomAttributes(typeof(XmlPayloadAttribute), false).FirstOrDefault();
if (attribute == null)
{
return;
}
operation.RequestBody = new OpenApiRequestBody() { Required = true };
var xml = @"<MyObject><Something/></MyObject>"; // How do I get this XML to appear as my example, verbatim?
operation.RequestBody.Content.Add("application/xml", new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Type = "string",
Example = new OpenApiString(xml) // This doesn't work!
},
Example = new OpenApiString(xml) // This doesn't work either!
});
}
}我将[XmlPayload]注释添加到我的端点,如下所示:
using System;
using System.IO;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
/// <summary>
/// My controller.
/// </summary>
[ApiController]
public class MyController : ControllerBase
{
/// <summary>
/// My Method.
/// </summary>
[Route("MyMethod")]
[HttpPost]
[XmlPayload]
public IActionResult MyMethod()
{
using var reader = new StreamReader(Request.Body);
var content = reader.ReadToEndAsync().Result;
// I deserialize and process the xml here
return new ContentResult
{
Content = /* My XML response goes here */,
ContentType = "application/xml",
StatusCode = StatusCodes.Status200OK
};
}
}Swagger正确地为post正文创建了一个输入字段,并正确地理解内容类型应该是"application/xml",但是使用以下内容填充该字段:
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML example cannot be generated; root element name is undefined -->如果我按以下方式使用Name:
operation.RequestBody = new OpenApiRequestBody() { Required = true };
var xml =
@"<s:MyRoot xmlns:s=""http://myschema"">
<s:MyTag>
</s:MyTag>
</s:MyRoot>";
operation.RequestBody.Content.Add("application/xml", new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Xml = new OpenApiXml
{
Name = "MyRoot",
Namespace = new Uri("http://myschema")
},
Example = new OpenApiString(xml, true)
},
});我得到:
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot xmlns="http://myschema/"><s:MyRoot
xmlns:s="http://myschema">
<s:MyTag>
</s:MyTag>
</s:MyRoot></MyRoot>无论是否使用Namespace,以及是否将OpenApiString的isExplicit参数设置为true或false,我都会得到相同的结果。
如何让Swagger逐字显示XML (如何修复C#)?
发布于 2022-08-09 08:51:24
operation.RequestBody.Content.Add("application/xml", new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Type = "string",
Xml = new OpenApiXml()
{
Name = "<RootElementNameHere>"
},
Example = new OpenApiString(xml) // This doesn't work!
},
Example = new OpenApiString(xml) // This doesn't work either!
});为了逐字显示示例(没有转义),您需要添加一个DTO并生成它的模式。
属性类中的
[AttributeUsage(validOn: AttributeTargets.Method, AllowMultiple = true)]
public class XmlPayloadAttribute : Attribute
{
public XmlPayloadAttribute(Type type, string? example = null)
{
ParameterName = "payload";
Required = true;
MediaType = "application/xml";
Format = "xml";
ParameterExample = example;
ParameterType = type;
}
public string Format { get; set; }
public string MediaType { get; set; }
public bool Required { get; set; }
public string ParameterName { get; set; }
public Type ParameterType { get; set; }
public string? ParameterExample { get; set; }
}在筛选器中,将通过属性指定的所有示例添加到方法
中。
public class XmlPayloadFilter : IOperationFilter
{
private string FormatXml(string xml)
{
try
{
XDocument doc = XDocument.Parse(xml);
return doc.ToString();
}
catch (Exception)
{
return xml;
}
}
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var attributes = context.MethodInfo.GetCustomAttributes(typeof(XmlPayloadAttribute), false);
if (attributes == null || attributes.Length == 0)
{
return;
}
operation.RequestBody = new OpenApiRequestBody() { Required = true };
foreach (XmlPayloadAttribute attribute in attributes)
{
if (operation.RequestBody.Content.TryGetValue("application/xml", out var type))
{
type.Examples.Add($"{attribute.ParameterType.Name}", new OpenApiExample() { Value = new OpenApiString(FormatXml(attribute.ParameterExample)) });
}
else
{
operation.RequestBody.Content.Add(
"application/xml",
new OpenApiMediaType
{
Schema = context.SchemaGenerator.GenerateSchema(attribute.ParameterType, context.SchemaRepository),
Examples = new Dictionary<string, OpenApiExample>
{
{
$"{attribute.ParameterType.Name}", new OpenApiExample() { Value = new OpenApiString(FormatXml(attribute.ParameterExample)) }
}
}
}
);
}
}
}
}的属性
[HttpPost("post")]
[XmlPayload(typeof(DTOClass1), "<ExampleXml1>")]
[XmlPayload(typeof(DTOClass2), "<ExampleXml2>")]
[XmlPayload(typeof(DTOClass3), "<ExampleXml3>")]
public async Task<IActionResult> post()
{
...
}https://stackoverflow.com/questions/73255545
复制相似问题