forked from RicoSuter/NSwag
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
IDocumentProvider
service and its implementation
- RicoSuter#1626 - does not "provide an api to generate multiple / all documents"; could be layered on this work - otherwise, meets requirements listed in RicoSuter#1626 - assumes the following answers to open questions in RicoSuter#1626 (generally means everything is opt-in) - without an `AddSwagger()` call, `IDocumentProvider` service will not exist - registered document name / identifier is new `SwaggerSettings<>.DocumentName` property - document is not registered unless `DocumentName` is non-`null` i.e. `IDocumentProvider` won't know about it - `SwaggerSettings<>.MiddlewareBasePath` and `SwaggerRoute` are independent of `DocumentName` - middleware does not depend on the `IDocumentProvider` or registrar services; duplicating some code - many thanks to @rynowak for writing this proposal
- Loading branch information
Showing
7 changed files
with
337 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//----------------------------------------------------------------------- | ||
// <copyright file="DocumentRegistry.cs" company="NSwag"> | ||
// Copyright (c) Rico Suter. All rights reserved. | ||
// </copyright> | ||
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license> | ||
// <author>Rico Suter, mail@rsuter.com</author> | ||
//----------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace NSwag.AspNetCore | ||
{ | ||
internal class DocumentRegistry | ||
{ | ||
private readonly Dictionary<string, RegisteredDocument> _documents; | ||
|
||
public DocumentRegistry() | ||
{ | ||
_documents = new Dictionary<string, RegisteredDocument>(StringComparer.Ordinal); | ||
} | ||
|
||
public RegisteredDocument this[string documentName] | ||
{ | ||
get | ||
{ | ||
if (documentName == null) | ||
{ | ||
throw new ArgumentNullException(nameof(documentName)); | ||
} | ||
|
||
_documents.TryGetValue(documentName, out var document); | ||
return document; | ||
} | ||
|
||
set | ||
{ | ||
if (documentName == null) | ||
{ | ||
throw new ArgumentNullException(nameof(documentName)); | ||
} | ||
|
||
if (value == null) | ||
{ | ||
throw new ArgumentNullException(nameof(value)); | ||
} | ||
|
||
_documents[documentName] = value; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//----------------------------------------------------------------------- | ||
// <copyright file="IDocumentProvider.cs" company="NSwag"> | ||
// Copyright (c) Rico Suter. All rights reserved. | ||
// </copyright> | ||
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license> | ||
// <author>Rico Suter, mail@rsuter.com</author> | ||
//----------------------------------------------------------------------- | ||
|
||
using System.IO; | ||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.Extensions.ApiDescription | ||
{ | ||
// This service will be looked up by name from the service collection when using | ||
// the Microsoft.Extensions.ApiDescription tool | ||
internal interface IDocumentProvider | ||
{ | ||
Task GenerateAsync(string documentName, TextWriter writer); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
//----------------------------------------------------------------------- | ||
// <copyright file="NSwagDocumentProvider.cs" company="NSwag"> | ||
// Copyright (c) Rico Suter. All rights reserved. | ||
// </copyright> | ||
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license> | ||
// <author>Rico Suter, mail@rsuter.com</author> | ||
//----------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.ApiExplorer; | ||
using Microsoft.Extensions.ApiDescription; | ||
using Microsoft.Extensions.Options; | ||
using NSwag.SwaggerGeneration; | ||
using NSwag.SwaggerGeneration.AspNetCore; | ||
using NSwag.SwaggerGeneration.WebApi; | ||
|
||
namespace NSwag.AspNetCore | ||
{ | ||
internal class NSwagDocumentProvider : IDocumentProvider | ||
{ | ||
private readonly IApiDescriptionGroupCollectionProvider _apiDescriptionGroupCollectionProvider; | ||
private readonly IOptions<MvcOptions> _mvcOptions; | ||
private readonly IOptions<MvcJsonOptions> _mvcJsonOptions; | ||
private readonly DocumentRegistry _registry; | ||
|
||
public NSwagDocumentProvider( | ||
DocumentRegistry registry, | ||
IApiDescriptionGroupCollectionProvider apiDescriptionGroupCollectionProvider, | ||
IOptions<MvcOptions> mvcOptions, | ||
IOptions<MvcJsonOptions> mvcJsonOptions) | ||
{ | ||
if (apiDescriptionGroupCollectionProvider == null) | ||
{ | ||
throw new ArgumentNullException(nameof(apiDescriptionGroupCollectionProvider)); | ||
} | ||
|
||
if (mvcOptions == null) | ||
{ | ||
throw new ArgumentNullException(nameof(mvcOptions)); | ||
} | ||
|
||
if (mvcJsonOptions == null) | ||
{ | ||
throw new ArgumentNullException(nameof(mvcJsonOptions)); | ||
} | ||
|
||
if (registry == null) | ||
{ | ||
throw new ArgumentNullException(nameof(registry)); | ||
} | ||
|
||
_apiDescriptionGroupCollectionProvider = apiDescriptionGroupCollectionProvider; | ||
_mvcOptions = mvcOptions; | ||
_mvcJsonOptions = mvcJsonOptions; | ||
_registry = registry; | ||
} | ||
|
||
public async Task<SwaggerDocument> GenerateAsync(string documentName) | ||
{ | ||
if (documentName == null) | ||
{ | ||
throw new ArgumentNullException(nameof(documentName)); | ||
} | ||
|
||
var documentInfo = _registry[documentName]; | ||
if (documentInfo == null) | ||
{ | ||
throw new InvalidOperationException($"No registered document found for document name '{documentName}'."); | ||
} | ||
|
||
documentInfo.Settings.ApplySettings(_mvcJsonOptions.Value.SerializerSettings, _mvcOptions.Value); | ||
|
||
SwaggerDocument document; | ||
if (documentInfo.Settings is AspNetCoreToSwaggerGeneratorSettings aspnetcore) | ||
{ | ||
var generator = new AspNetCoreToSwaggerGenerator(aspnetcore, documentInfo.SchemaGenerator); | ||
document = await generator.GenerateAsync(_apiDescriptionGroupCollectionProvider.ApiDescriptionGroups); | ||
} | ||
else if (documentInfo.Settings is WebApiToSwaggerGeneratorSettings webapi) | ||
{ | ||
var generator = new WebApiToSwaggerGenerator(webapi, documentInfo.SchemaGenerator); | ||
document = await generator.GenerateForControllersAsync(webapi.ControllerTypes); | ||
} | ||
else | ||
{ | ||
throw new InvalidOperationException($"Unsupported settings type '{documentInfo.GetType().FullName}"); | ||
} | ||
|
||
documentInfo.PostProcess?.Invoke(document); | ||
|
||
return document; | ||
} | ||
|
||
// Called by the Microsoft.Extensions.ApiDescription tool | ||
async Task IDocumentProvider.GenerateAsync(string documentName, TextWriter writer) | ||
{ | ||
if (documentName == null) | ||
{ | ||
throw new ArgumentNullException(nameof(documentName)); | ||
} | ||
|
||
if (writer == null) | ||
{ | ||
throw new ArgumentNullException(nameof(writer)); | ||
} | ||
|
||
var document = await GenerateAsync(documentName); | ||
|
||
var json = document.ToJson(); | ||
await writer.WriteAsync(json); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
//----------------------------------------------------------------------- | ||
// <copyright file="RegisteredDocument.cs" company="NSwag"> | ||
// Copyright (c) Rico Suter. All rights reserved. | ||
// </copyright> | ||
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license> | ||
// <author>Rico Suter, mail@rsuter.com</author> | ||
//----------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using NSwag.SwaggerGeneration; | ||
using NSwag.SwaggerGeneration.AspNetCore; | ||
using NSwag.SwaggerGeneration.WebApi; | ||
|
||
namespace NSwag.AspNetCore | ||
{ | ||
// Captures the state required to produce a document. Mediates between two supported | ||
// document generators. | ||
internal class RegisteredDocument | ||
{ | ||
public static RegisteredDocument CreateAspNetCoreGeneratorDocument( | ||
AspNetCoreToSwaggerGeneratorSettings settings, | ||
SwaggerJsonSchemaGenerator schemaGenerator, | ||
Action<SwaggerDocument> postProcess) | ||
{ | ||
return new RegisteredDocument() | ||
{ | ||
PostProcess = postProcess, | ||
SchemaGenerator = schemaGenerator, | ||
Settings = settings, | ||
}; | ||
} | ||
|
||
public static RegisteredDocument CreateWebApiGeneratorDocument( | ||
WebApiToSwaggerGeneratorSettings settings, | ||
IEnumerable<Type> controllerTypes, | ||
SwaggerJsonSchemaGenerator schemaGenerator, | ||
Action<SwaggerDocument> postProcess) | ||
{ | ||
return new RegisteredDocument() | ||
{ | ||
ControllerTypes = controllerTypes, | ||
PostProcess = postProcess, | ||
SchemaGenerator = schemaGenerator, | ||
Settings = settings, | ||
}; | ||
} | ||
|
||
private RegisteredDocument() | ||
{ | ||
} | ||
|
||
public IEnumerable<Type> ControllerTypes { get; private set; } | ||
|
||
public Action<SwaggerDocument> PostProcess { get; private set; } | ||
|
||
public SwaggerJsonSchemaGenerator SchemaGenerator { get; private set; } | ||
|
||
public SwaggerGeneratorSettings Settings { get; private set; } | ||
} | ||
} |
Oops, something went wrong.