首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >6: ASP.NET POST体示例

6: ASP.NET POST体示例
EN

Stack Overflow用户
提问于 2022-08-05 21:41:28
回答 1查看 1.4K关注 0票数 1

我有一个ASP.NET CoreWebAPI6.0项目,该项目包含一个端点,它的POST正文(application/ XML )中需要xml。我创建了一个属性如下:

代码语言:javascript
运行
复制
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过滤器如下所示:

代码语言:javascript
运行
复制
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]注释添加到我的端点,如下所示:

代码语言:javascript
运行
复制
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",但是使用以下内容填充该字段:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML example cannot be generated; root element name is undefined -->

如果我按以下方式使用Name

代码语言:javascript
运行
复制
        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)
            },
        });

我得到:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot xmlns="http://myschema/">&lt;s:MyRoot 
xmlns:s=&quot;http://myschema&quot;&gt;
    &lt;s:MyTag&gt;
    &lt;/s:MyTag&gt;
&lt;/s:MyRoot&gt;</MyRoot>

无论是否使用Namespace,以及是否将OpenApiStringisExplicit参数设置为true或false,我都会得到相同的结果。

如何让Swagger逐字显示XML (如何修复C#)?

EN

回答 1

Stack Overflow用户

发布于 2022-08-09 08:51:24

代码语言:javascript
运行
复制
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并生成它的模式。

属性类中的

  1. ,添加属性类型和示例

代码语言:javascript
运行
复制
    [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; }
    }

在筛选器中,将通过属性指定的所有示例添加到方法

中。

代码语言:javascript
运行
复制
    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)) }
                                }
                            }
                        }
                    );
                }
            }
        }
    }

  1. 使用类似于

的属性

代码语言:javascript
运行
复制
    [HttpPost("post")]
    [XmlPayload(typeof(DTOClass1), "<ExampleXml1>")]
    [XmlPayload(typeof(DTOClass2), "<ExampleXml2>")]
    [XmlPayload(typeof(DTOClass3), "<ExampleXml3>")]
    public async Task<IActionResult> post()
    {
        ...
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73255545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档