Skip to content
Rico Suter edited this page Jun 13, 2019 · 20 revisions

The JsonSchemaGenerator automatically loads .NET XML Documentation files to populate the JSON Schema/Swagger/OpenAPI attributes summary, description and others. The XML file is searched in the directory of the type's assembly with the assembly file name but with the file extension .xml. This XML file is only generated when enabled in the project settings.

The XML Documentation reader uses reflection to support multiple platforms in a single PCL. In order to work, following types must be available:

  • System.IO.File
  • System.IO.Path
  • System.Xml.XPath.Extensions

.NET Core

To make the required types available in a .NET Core process (i.e. in your ASP.NET Core application), you may need to install the following NuGet packages:

Define examples

The schema example object can be set with the example xml docs:

/// <example>
/// { "name": "Smith" }
/// </example>
public class Person
{
    public string Name { get; set; }

Custom XML Documentation

It is possible to add custom XML Documentation processing using a custom Contract Resolver as follows:

//Use this contract resolver to automatically use the text from XML Documentaiton Example tags in output Json
/// <summary>
/// Custom contract resolver that includes XML Documentation "example" information in the Json.
/// </summary>
public class ExampleDocContractResolver : DefaultContractResolver
{    
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {            
        var property = base.CreateProperty(member, memberSerialization);
        //Use our custom attribute provider.
        property.AttributeProvider = new ExampleAttributeProvider(property.AttributeProvider, member);
        return property;
    }
}

/// <summary>
/// AttributeProvider that appends a JsonSchemaExtensionDataAttribute
/// with "example" from Xml Documentation.
/// </summary>
public class ExampleAttributeProvider : IAttributeProvider
{
    private readonly IAttributeProvider originalProvider;
    private readonly MemberInfo memberInfo;

    public ExampleAttributeProvider(IAttributeProvider originalProvider, MemberInfo memberInfo)
    {
        this.originalProvider = originalProvider;
        this.memberInfo = memberInfo;
    }

    private IList<Attribute> AddExampleAttribute(IList<Attribute> source)
    {
        //If there is already an example explicitly defined for Json, just use that.
        if (!source.Any(a => a.GetType().IsAssignableTo("JsonSchemaExtensionDataAttribute", TypeNameStyle.Name) && (a as JsonSchemaExtensionDataAttribute).Key == "example"))
        {
            var example = memberInfo.GetXmlDocumentationTagAsync("example").Result;
            if (!string.IsNullOrWhiteSpace(example))
            {
                source.Add(
                    new JsonSchemaExtensionDataAttribute(
                        "example",
                        example
                    )
                );
            }
        }

        return source;
    }

    public IList<Attribute> GetAttributes(bool inherit)
    {
        var properties = new List<Attribute>(originalProvider.GetAttributes(inherit));
        AddExampleAttribute(properties);
        return properties;
    }

    public IList<Attribute> GetAttributes(Type attributeType, bool inherit)
    {
        var properties = new List<Attribute>(originalProvider.GetAttributes(attributeType, inherit));
        AddExampleAttribute(properties);
        return properties;
    }
}
Clone this wiki locally