Skip to content

Commit

Permalink
Add CreateWebHostBuilderMethod & AspNetCoreEnvironment setting, imple…
Browse files Browse the repository at this point in the history
…ment UseDocumentProvider & DocumentName (#1655)

* Add CreateWebHostBuilderMethod setting

* Fix build

* Fix build

* Improve ui

* Disable test

* Implement UseDocumentProvider, add DocumentName and AspNetCoreEnvironment setting

* Improve exception handling and support method with no args

* Transform old documents

* Improve ui
  • Loading branch information
RicoSuter authored Nov 2, 2018
1 parent 84932e4 commit 95b0b27
Show file tree
Hide file tree
Showing 22 changed files with 358 additions and 208 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public static IServiceCollection AddSwagger(this IServiceCollection serviceColle
serviceCollection.AddSingleton<IConfigureOptions<MvcOptions>, SwaggerConfigureMvcOptions>();
serviceCollection.AddSingleton<SwaggerDocumentProvider>();

// Used by UseDocumentProvider CLI setting
serviceCollection.AddSingleton<ISwaggerDocumentProvider>(s => s.GetRequiredService<SwaggerDocumentProvider>());

// Used by the Microsoft.Extensions.ApiDescription tool
serviceCollection.AddSingleton<ApiDescription.IDocumentProvider>(s => s.GetRequiredService<SwaggerDocumentProvider>());

Expand Down
5 changes: 3 additions & 2 deletions src/NSwag.AspNetCore/SwaggerDocumentProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
//-----------------------------------------------------------------------

using Microsoft.Extensions.ApiDescription;
using NSwag.SwaggerGeneration;
using System;
using System.IO;
using System.Threading.Tasks;

namespace NSwag.AspNetCore
{
internal class SwaggerDocumentProvider : IDocumentProvider
internal class SwaggerDocumentProvider : IDocumentProvider, ISwaggerDocumentProvider
{
private readonly IServiceProvider _serviceProvider;
private readonly SwaggerDocumentRegistry _registry;
Expand All @@ -34,7 +35,7 @@ public async Task<SwaggerDocument> GenerateAsync(string documentName)
_registry.Documents.TryGetValue(documentName, out var settings);
if (settings == null)
{
throw new InvalidOperationException($"No registered OpenAPI/Swagger document found for document name '{documentName}'. " +
throw new InvalidOperationException($"No registered OpenAPI/Swagger document found for the document name '{documentName}'. " +
$"Add with the AddSwagger()/AddOpenApi() methods in ConfigureServices().");
}

Expand Down
4 changes: 2 additions & 2 deletions src/NSwag.Commands/Commands/IsolatedCommandBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private static string[] LoadDefaultNugetCache()
return new[] { Path.GetFullPath(path) };
}

#if NET451
#if NET461
public IEnumerable<string> GetAssemblies(string assemblyDirectory)
{
var codeBaseDirectory = Path.GetDirectoryName(new Uri(typeof(IsolatedCommandBase<>).GetTypeInfo().Assembly.CodeBase).LocalPath);
Expand Down Expand Up @@ -122,7 +122,7 @@ public IEnumerable<Assembly> GetAssemblies(string assemblyDirectory)

public IEnumerable<BindingRedirect> GetBindingRedirects()
{
#if NET451
#if NET461
yield return new BindingRedirect("Newtonsoft.Json", typeof(JToken), "30ad4fe6b2a6aeed");
yield return new BindingRedirect("NJsonSchema", typeof(JsonSchema4), "c2f9c3bdfae56102");
yield return new BindingRedirect("NSwag.Core", typeof(SwaggerDocument), "c2d88086e098d109");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public abstract class IsolatedSwaggerOutputCommandBase<T> : IsolatedCommandBase<
[JsonProperty("output", NullValueHandling = NullValueHandling.Include)]
public string OutputFilePath { get; set; }

[Argument(Name = "OutputType", IsRequired = false, Description = "Specifies the output schema type (Swagger2|OpenApi3, default: Swagger2).")]
[Argument(Name = "OutputType", IsRequired = false, Description = "Specifies the output schema type, ignored when UseDocumentProvider is enabled (Swagger2|OpenApi3, default: Swagger2).")]
public SchemaType OutputType
{
get { return Settings.SchemaType; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
using NSwag.SwaggerGeneration.AspNetCore;
using NJsonSchema.Yaml;
using NJsonSchema;
using Microsoft.AspNetCore.Hosting;
using NSwag.SwaggerGeneration;

#if NETCOREAPP || NETSTANDARD
using System.Runtime.Loader;
Expand Down Expand Up @@ -67,9 +69,19 @@ public bool RequireParametersWithoutDefault

public override async Task<object> RunAsync(CommandLineProcessor processor, IConsoleHost host)
{
// Run with .csproj
if (!string.IsNullOrEmpty(Project))
if (!string.IsNullOrEmpty(Project) && AssemblyPaths.Any())
{
throw new InvalidOperationException("Either provide a Project or an assembly but not both.");
}

if (string.IsNullOrEmpty(Project))
{
// Run with assembly
return await base.RunAsync(processor, host);
}
else
{
// Run with .csproj
var verboseHost = Verbose ? host : null;

var projectFile = ProjectMetadata.FindProject(Project);
Expand All @@ -93,7 +105,7 @@ public override async Task<object> RunAsync(CommandLineProcessor processor, ICon
var args = new List<string>();
string executable;

#if NET451
#if NET461
var toolDirectory = AppDomain.CurrentDomain.BaseDirectory;
if (!Directory.Exists(toolDirectory))
toolDirectory = Path.GetDirectoryName(typeof(AspNetCoreToSwaggerCommand).GetTypeInfo().Assembly.Location);
Expand Down Expand Up @@ -170,6 +182,7 @@ public override async Task<object> RunAsync(CommandLineProcessor processor, ICon
args.Add(outputFile);
args.Add(projectMetadata.AssemblyName);
args.Add(toolDirectory);

try
{
var exitCode = await Exe.RunAsync(executable, args, verboseHost).ConfigureAwait(false);
Expand All @@ -190,14 +203,15 @@ public override async Task<object> RunAsync(CommandLineProcessor processor, ICon
TryDeleteFiles(cleanupFiles);
}
}
else
{
return await base.RunAsync(processor, host);
}
}

public string ChangeWorkingDirectory()
internal string ChangeWorkingDirectoryAndSetAspNetCoreEnvironment()
{
if (!string.IsNullOrEmpty(AspNetCoreEnvironment))
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", AspNetCoreEnvironment);
}

var currentWorkingDirectory = Directory.GetCurrentDirectory();

if (!string.IsNullOrEmpty(WorkingDirectory))
Expand All @@ -224,26 +238,40 @@ public string ChangeWorkingDirectory()
return currentWorkingDirectory;
}

protected override async Task<string> RunIsolatedAsync(AssemblyLoader.AssemblyLoader assemblyLoader)
public async Task<SwaggerDocument> GenerateDocumentAsync(AssemblyLoader.AssemblyLoader assemblyLoader, IWebHost host, string currentWorkingDirectory)
{
InitializeCustomTypes(assemblyLoader);
Directory.SetCurrentDirectory(currentWorkingDirectory);

var startupType = await GetStartupTypeAsync(assemblyLoader);
var currentWorkingDirectory = ChangeWorkingDirectory();
using (var testServer = CreateTestServer(startupType))
if (UseDocumentProvider)
{
Directory.SetCurrentDirectory(currentWorkingDirectory);
var documentProvider = host.Services.GetRequiredService<ISwaggerDocumentProvider>();
var document = await documentProvider.GenerateAsync(DocumentName);
return document;
}
else
{
InitializeCustomTypes(assemblyLoader);

// See https://github.com/aspnet/Mvc/issues/5690
var type = typeof(IApiDescriptionGroupCollectionProvider);
var apiDescriptionProvider = (IApiDescriptionGroupCollectionProvider)testServer.Host.Services.GetRequiredService(type);
// In the case of KeyNotFoundException, see https://github.com/aspnet/Mvc/issues/5690
var apiDescriptionProvider = host.Services.GetRequiredService<IApiDescriptionGroupCollectionProvider>();

var settings = await CreateSettingsAsync(assemblyLoader, testServer.Host, currentWorkingDirectory);
var settings = await CreateSettingsAsync(assemblyLoader, host, currentWorkingDirectory);
var generator = new AspNetCoreToSwaggerGenerator(settings);
var document = await generator.GenerateAsync(apiDescriptionProvider.ApiDescriptionGroups).ConfigureAwait(false);

var json = PostprocessDocument(document);
return json;
PostprocessDocument(document);

return document;
}
}

protected override async Task<string> RunIsolatedAsync(AssemblyLoader.AssemblyLoader assemblyLoader)
{
var currentWorkingDirectory = ChangeWorkingDirectoryAndSetAspNetCoreEnvironment();
using (var testServer = await CreateTestServerAsync(assemblyLoader))
{
var document = await GenerateDocumentAsync(assemblyLoader, testServer.Host, currentWorkingDirectory);
return UseDocumentProvider ? document.ToJson() : document.ToJson(OutputType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using NSwag.SwaggerGeneration.AspNetCore;

namespace NSwag.Commands.SwaggerGeneration.AspNetCore
{
Expand All @@ -25,19 +22,14 @@ public static void Process(string commandContent, string outputFile, string appl
{
var command = JsonConvert.DeserializeObject<AspNetCoreToSwaggerCommand>(commandContent);

var previousWorkingDirectory = command.ChangeWorkingDirectory();
var previousWorkingDirectory = command.ChangeWorkingDirectoryAndSetAspNetCoreEnvironment();
var webHost = GetWebHost(applicationName);

Directory.SetCurrentDirectory(previousWorkingDirectory);

var apiDescriptionProvider = webHost.Services.GetRequiredService<IApiDescriptionGroupCollectionProvider>();

var assemblyLoader = new AssemblyLoader.AssemblyLoader();
var settings = Task.Run(async () => await command.CreateSettingsAsync(assemblyLoader, webHost, previousWorkingDirectory)).GetAwaiter().GetResult();
var document = Task.Run(async () =>
await command.GenerateDocumentAsync(assemblyLoader, webHost, previousWorkingDirectory)).GetAwaiter().GetResult();

var generator = new AspNetCoreToSwaggerGenerator(settings);
var document = generator.GenerateAsync(apiDescriptionProvider.ApiDescriptionGroups).GetAwaiter().GetResult();
var json = command.PostprocessDocument(document);
var json = command.UseDocumentProvider ? document.ToJson() : document.ToJson(command.OutputType);

var outputPathDirectory = Path.GetDirectoryName(outputFile);
Directory.CreateDirectory(outputPathDirectory);
Expand Down
Loading

0 comments on commit 95b0b27

Please sign in to comment.