让 Swagger 输出 IRouteConstraint 的描述
Make Swagger output the description of an IRouteConstraint
我有一条带有自定义 IRouteConstraint 的路线。
Swagger 生成参数部分,但描述字段始终为空。对于其他参数,我从 XML 评论中得到了正确的描述。
到目前为止我发现的唯一解决方法是添加一个操作过滤器并在那里设置
的描述
foreach ( var parameter in operation.Parameters.OfType<NonBodyParameter>() )
{
if (parameter.Name == RouteConstraint.Name)
{
parameter.Description = GetConstraintDescription();
}
指示 swagger 从 IRouteConstraints 的 XML 评论中获取描述的任何方法。
恐怕唯一的"easy way"是你已经实现的(操作过滤器)
我正在查看您的项目输出的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 中提取描述,但除此之外我看不到任何其他方法。
我当前的解决方案是 class,基于 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));
})
我有一条带有自定义 IRouteConstraint 的路线。 Swagger 生成参数部分,但描述字段始终为空。对于其他参数,我从 XML 评论中得到了正确的描述。 到目前为止我发现的唯一解决方法是添加一个操作过滤器并在那里设置
的描述 foreach ( var parameter in operation.Parameters.OfType<NonBodyParameter>() )
{
if (parameter.Name == RouteConstraint.Name)
{
parameter.Description = GetConstraintDescription();
}
指示 swagger 从 IRouteConstraints 的 XML 评论中获取描述的任何方法。
恐怕唯一的"easy way"是你已经实现的(操作过滤器)
我正在查看您的项目输出的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 中提取描述,但除此之外我看不到任何其他方法。
我当前的解决方案是 class,基于 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));
})