【问题标题】:Make Swagger output the description of an IRouteConstraint使 Swagger 输出 IRouteConstraint 的描述
【发布时间】:2018-03-09 15:48:02
【问题描述】:

我有一条带有自定义 IRouteConstraint 的路线。 Swagger 生成参数部分,但描述字段始终为空。对于其他参数,我正确地从 XML cmets 获得了描述。 到目前为止我发现的唯一解决方法是添加一个操作过滤器并在那里为

设置描述
 foreach ( var parameter in operation.Parameters.OfType<NonBodyParameter>() )
        {
            if (parameter.Name == RouteConstraint.Name)
            {
                parameter.Description = GetConstraintDescription();
            }

指示 swagger 从 IRouteConstraints 的 XML cmets 获取描述的任何方式。

【问题讨论】:

  • 你能给我们看更多的代码吗?或者在 GitHub 上创建一个最小的项目并发布一个链接?
  • 我做了一个非常简单的示例:github.com/apopovsky/swagger-web-test 如果你浏览到 /swagger/v1/swagger.json 你会看到 id 参数有一个描述(来自 xml 文档)但是“sector”约束没有。

标签: asp.net-core swagger asp.net-core-webapi swashbuckle


【解决方案1】:

恐怕唯一的“简单方法”是您已经实现的(操作过滤器)

我正在查看您的项目输出的 XML 描述

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>SwaggerWeb</name>
    </assembly>
    <members>
        <member name="M:SwaggerWeb.Controllers.ValuesController.Get(System.Int32)">
            <summary> Get by ID </summary>
            <param name="id">The value ID</param>
            <returns></returns>
        </member>
        <member name="T:SwaggerWeb.SectorRouteConstraint">
            <summary> Sector constraint </summary>
        </member>
    </members>
</doc>

您可以尝试使您的过滤器更通用一些,并从 XML 中提取描述,但除此之外我没有看到任何其他方式。

【讨论】:

  • 我也这么认为,但我是 Swager 和 Swashbuckle 的新手,所以也许有人知道另一种方式。谢谢!
  • @ArielPopovsky 理论上有办法! Swashbuckle 在完美世界中是开源的,应该在那里进行更正,但我认为这是一个非常边缘的案例,不确定这会给社区带来很多好处
【解决方案2】:

我目前的解决方案是这个类,基于 Swashbuckle XmlCommentsOperationFilter。

public class RouteConstraintXmlDocsOperationFilter:IOperationFilter
{
    private readonly XPathNavigator _xmlNavigator;
    private const string MemberXPath = "/doc/members/member[@name='{0}']";
    private const string SummaryXPath = "summary";


    public RouteConstraintXmlDocsOperationFilter(string filePath)
    {
        XPathDocument xmlDoc = new XPathDocument(filePath);
        _xmlNavigator = xmlDoc.CreateNavigator();
    }


    public void Apply(Operation operation, OperationFilterContext context)
    {
        ApplyConstraintsXmlToActionParameters(operation.Parameters, context.ApiDescription);
    }

    private void ApplyConstraintsXmlToActionParameters(IList<IParameter> parameters, ApiDescription apiDescription)
    {
        var nonBodyParameters = parameters.OfType<NonBodyParameter>();
        foreach (var parameter in nonBodyParameters)
        {                // Check for a corresponding action parameter?
            var actionParameter = apiDescription.ParameterDescriptions.FirstOrDefault(p =>
                parameter.Name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
            if (actionParameter == null) continue;

            if (!actionParameter.RouteInfo.Constraints.Any()) continue;

            var constraintType = actionParameter.RouteInfo.Constraints.FirstOrDefault().GetType();
            var commentIdForType = XmlCommentsIdHelper.GetCommentIdForType(constraintType);
            var constraintSummaryNode = _xmlNavigator
                .SelectSingleNode(string.Format(MemberXPath, commentIdForType))
                ?.SelectSingleNode(SummaryXPath);
            if (constraintSummaryNode != null)
            {
                parameter.Description = XmlCommentsTextHelper.Humanize(constraintSummaryNode.InnerXml);
            }
        }
    }
}

设置:

services.AddSwaggerGen(o =>
        {
            var fileName = GetType().GetTypeInfo().Module.Name.Replace(".dll", ".xml").Replace(".exe", ".xml");
            o.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, fileName));
            o.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
            o.OperationFilter<RouteConstraintXmlDocsOperationFilter>(Path.Combine(AppContext.BaseDirectory, fileName));
        })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 2020-11-21
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多