Skip to content

Commit 12237af

Browse files
Add XML docs descriptions
Add OpenAPI descriptions for schemas from XML documentation.
1 parent 1b624c5 commit 12237af

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

src/API/API.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<InvariantGlobalization>true</InvariantGlobalization>
1111
<OutputType>Exe</OutputType>
1212
<PreserveCompilationContext>true</PreserveCompilationContext>
13-
<PublishAot>true</PublishAot>
13+
<PublishAot>false</PublishAot>
1414
<PublishSelfContained>true</PublishSelfContained>
1515
<RootNamespace>MartinCostello.Api</RootNamespace>
1616
<TargetFramework>net9.0</TargetFramework>

src/API/Extensions/IServiceCollectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public static IServiceCollection AddOpenApiDocumentation(this IServiceCollection
3939
options.AddOperationTransformer<AddResponseDescriptionTransformer>();
4040
options.AddOperationTransformer<RemoveStyleCopPrefixesTransformer>();
4141
options.AddSchemaTransformer<AddExamplesTransformer>();
42+
options.AddSchemaTransformer<AddSchemaDescriptionsTransformer>();
4243
options.AddSchemaTransformer<RemoveStyleCopPrefixesTransformer>();
4344
});
4445

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Martin Costello, 2016. All rights reserved.
2+
// Licensed under the MIT license. See the LICENSE file in the project root for full license information.
3+
4+
using System.Xml;
5+
using System.Xml.XPath;
6+
using Microsoft.AspNetCore.OpenApi;
7+
using Microsoft.OpenApi.Models;
8+
9+
namespace MartinCostello.Api.OpenApi;
10+
11+
/// <summary>
12+
/// A class that adds descriptions to the schemas of OpenAPI documents. This class cannot be inherited.
13+
/// </summary>
14+
public sealed class AddSchemaDescriptionsTransformer : IOpenApiSchemaTransformer
15+
{
16+
/// <inheritdoc/>
17+
public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext context, CancellationToken cancellationToken)
18+
{
19+
if (schema.Description != null)
20+
{
21+
return Task.CompletedTask;
22+
}
23+
24+
var thisAssembly = GetType().Assembly;
25+
26+
if (context.JsonTypeInfo.Type.Assembly == thisAssembly)
27+
{
28+
var navigator = CreateNavigator();
29+
var description = navigator.SelectSingleNode($"/doc/members/member[@name='T:{context.JsonTypeInfo.Type.FullName}']/summary");
30+
31+
if (!string.IsNullOrEmpty(description?.InnerXml))
32+
{
33+
schema.Description = description.Value.Trim();
34+
}
35+
}
36+
else if (context.JsonPropertyInfo?.DeclaringType.Assembly == thisAssembly)
37+
{
38+
var navigator = CreateNavigator();
39+
40+
var typeName = context.JsonPropertyInfo.DeclaringType.FullName;
41+
var propertyName = $"{char.ToUpperInvariant(context.JsonPropertyInfo.Name[0])}{context.JsonPropertyInfo.Name[1..]}";
42+
43+
var description = navigator.SelectSingleNode(
44+
$"/doc/members/member[@name='P:{typeName}{Type.Delimiter}{propertyName}']/summary");
45+
46+
if (!string.IsNullOrEmpty(description?.InnerXml))
47+
{
48+
schema.Description = description.Value.Trim();
49+
}
50+
}
51+
52+
return Task.CompletedTask;
53+
}
54+
55+
private static XPathNavigator CreateNavigator()
56+
{
57+
var path = Path.Combine(AppContext.BaseDirectory, "API.xml");
58+
using var reader = XmlReader.Create(path);
59+
return new XPathDocument(reader).CreateNavigator();
60+
}
61+
}

0 commit comments

Comments
 (0)