Skip to content

Instantly share code, notes, and snippets.

@magnusbakken
Created January 31, 2022 10:38
Show Gist options
  • Save magnusbakken/d3329b65ac5d9493bf112d6b8a88705b to your computer and use it in GitHub Desktop.
Save magnusbakken/d3329b65ac5d9493bf112d6b8a88705b to your computer and use it in GitHub Desktop.
A custom Swashbuckle schema filter that adds remarks to schema descriptions.
using System.Xml.XPath;
using Microsoft.OpenApi.Models;
namespace Swashbuckle.AspNetCore.SwaggerGen;
// This is a slightly modified version of the built-in XmlCommentsSchemaFilter.
// Currently our only modifications are that we append the contents of the <remarks> section to the description for each schema item.
public class CustomXmlCommentsSchemaFilter : ISchemaFilter
{
private readonly XPathNavigator _xmlNavigator;
public CustomXmlCommentsSchemaFilter(XPathDocument xmlDoc)
{
_xmlNavigator = xmlDoc.CreateNavigator();
}
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
ApplyTypeTags(schema, context.Type);
if (context.MemberInfo != null)
{
ApplyMemberTags(schema, context);
}
}
private void ApplyTypeTags(OpenApiSchema schema, Type type)
{
var typeMemberName = XmlCommentsNodeNameHelper.GetMemberNameForType(type);
var typeNode = _xmlNavigator.SelectSingleNode($"/doc/members/member[@name='{typeMemberName}']");
if (typeNode == null)
return;
var typeSummaryNode = typeNode.SelectSingleNode("summary");
if (typeSummaryNode != null)
schema.Description = XmlCommentsTextHelper.Humanize(typeSummaryNode.InnerXml);
// This is the part we've added. Remarks are appended to the description with a couple of linebreaks in between.
var typeRemarksNode = typeNode.SelectSingleNode("remarks");
if (typeRemarksNode != null)
schema.Description = $"{schema.Description}\r\n\r\n{XmlCommentsTextHelper.Humanize(typeRemarksNode.InnerXml)}";
}
private void ApplyMemberTags(OpenApiSchema schema, SchemaFilterContext context)
{
var fieldOrPropertyMemberName = XmlCommentsNodeNameHelper.GetMemberNameForFieldOrProperty(context.MemberInfo);
var fieldOrPropertyNode = _xmlNavigator.SelectSingleNode($"/doc/members/member[@name='{fieldOrPropertyMemberName}']");
if (fieldOrPropertyNode == null) return;
var summaryNode = fieldOrPropertyNode.SelectSingleNode("summary");
if (summaryNode != null)
schema.Description = XmlCommentsTextHelper.Humanize(summaryNode.InnerXml);
// This is the part we've added. Remarks are appended to the description with a couple of linebreaks in between.
var remarksNode = fieldOrPropertyNode.SelectSingleNode("remarks");
if (remarksNode != null)
schema.Description = $"{schema.Description}\r\n\r\n{XmlCommentsTextHelper.Humanize(remarksNode.InnerXml)}";
var exampleNode = fieldOrPropertyNode.SelectSingleNode("example");
if (exampleNode != null)
{
var exampleAsJson = (schema.ResolveType(context.SchemaRepository) == "string")
? $"\"{exampleNode.InnerXml}\""
: exampleNode.InnerXml;
schema.Example = OpenApiAnyFactory.CreateFromJson(exampleAsJson);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment