public async Task When_generating_multiple_types_then_they_are_appended_to_the_definitions() { //// Arrange var classNames = new[] { "NSwag.SwaggerGeneration.WebApi.Tests.B", "NSwag.SwaggerGeneration.WebApi.Tests.C" }; //// Act var document = new SwaggerDocument(); var settings = new JsonSchemaGeneratorSettings(); var schemaResolver = new SwaggerSchemaResolver(document, settings); var generator = new JsonSchemaGenerator(settings); foreach (var className in classNames) { var type = typeof(TypesToSwaggerTests).Assembly.GetType(className); await generator.GenerateAsync(type, schemaResolver).ConfigureAwait(false); } var json = document.ToJson(); //// Assert Assert.IsNotNull(json); Assert.AreEqual(2, document.Definitions.Count); }
protected override async Task <string> RunIsolatedAsync(AssemblyLoader.AssemblyLoader assemblyLoader) { var document = new SwaggerDocument(); var generator = new JsonSchemaGenerator(Settings); var schemaResolver = new SwaggerSchemaResolver(document, Settings); #if FullNet var assemblies = PathUtilities.ExpandFileWildcards(AssemblyPaths) .Select(path => Assembly.LoadFrom(path)).ToArray(); #else var currentDirectory = await DynamicApis.DirectoryGetCurrentDirectoryAsync().ConfigureAwait(false); var assemblies = PathUtilities.ExpandFileWildcards(AssemblyPaths) .Select(path => assemblyLoader.Context.LoadFromAssemblyPath(PathUtilities.MakeAbsolutePath(path, currentDirectory))).ToArray(); #endif var allExportedClassNames = assemblies.SelectMany(a => a.ExportedTypes).Select(t => t.FullName).ToList(); var matchedClassNames = ClassNames .SelectMany(n => PathUtilities.FindWildcardMatches(n, allExportedClassNames, '.')) .Distinct(); foreach (var className in matchedClassNames) { var type = assemblies.Select(a => a.GetType(className)).FirstOrDefault(t => t != null); await generator.GenerateAsync(type, schemaResolver).ConfigureAwait(false); } return(document.ToJson()); }
/// <summary>Generates a Swagger specification for the given controller types.</summary> /// <param name="controllerTypes">The types of the controller.</param> /// <returns>The <see cref="SwaggerDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <SwaggerDocument> GenerateForControllersAsync(IEnumerable <Type> controllerTypes) { var document = await CreateDocumentAsync().ConfigureAwait(false); var schemaResolver = new SwaggerSchemaResolver(document, Settings); var usedControllerTypes = new List <Type>(); foreach (var controllerType in controllerTypes) { var generator = new SwaggerGenerator(_schemaGenerator, Settings, schemaResolver); var isIncluded = await GenerateForControllerAsync(document, controllerType, generator, schemaResolver).ConfigureAwait(false); if (isIncluded) { usedControllerTypes.Add(controllerType); } } document.GenerateOperationIds(); foreach (var processor in Settings.DocumentProcessors) { await processor.ProcessAsync(new DocumentProcessorContext(document, controllerTypes, usedControllerTypes, schemaResolver, _schemaGenerator, Settings)); } return(document); }
/// <summary>Generates a Swagger specification for the given <see cref="ApiDescriptionGroupCollection"/>.</summary> /// <param name="apiDescriptionGroups">The <see cref="ApiDescriptionGroupCollection"/>.</param> /// <returns>The <see cref="SwaggerDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <SwaggerDocument> GenerateAsync(ApiDescriptionGroupCollection apiDescriptionGroups) { var apiDescriptions = apiDescriptionGroups.Items .Where(group => Settings.ApiGroupNames == null || Settings.ApiGroupNames.Length == 0 || Settings.ApiGroupNames.Contains(group.GroupName)) .SelectMany(g => g.Items) .Where(apiDescription => apiDescription.ActionDescriptor is ControllerActionDescriptor) .ToArray(); var document = await CreateDocumentAsync().ConfigureAwait(false); var schemaResolver = new SwaggerSchemaResolver(document, Settings); var apiGroups = apiDescriptions .Select(apiDescription => new Tuple <ApiDescription, ControllerActionDescriptor>(apiDescription, (ControllerActionDescriptor)apiDescription.ActionDescriptor)) .GroupBy(item => item.Item2.ControllerTypeInfo.AsType()) .ToArray(); var usedControllerTypes = await GenerateForControllersAsync(document, apiGroups, schemaResolver).ConfigureAwait(false); document.GenerateOperationIds(); var controllerTypes = apiGroups.Select(k => k.Key).ToArray(); foreach (var processor in Settings.DocumentProcessors) { await processor.ProcessAsync(new DocumentProcessorContext(document, controllerTypes, usedControllerTypes, schemaResolver, _schemaGenerator, Settings)); } return(document); }
private AspNetCoreOperationProcessorContext GetContext(ApiDescription apiDescription) { var operationDescription = new SwaggerOperationDescription { Operation = new SwaggerOperation() }; var swaggerSettings = new AspNetCoreToSwaggerGeneratorSettings(); var document = new SwaggerDocument(); var generator = new AspNetCoreToSwaggerGenerator(swaggerSettings); var schemaGeneratorSettings = new JsonSchemaGeneratorSettings(); var schemaGenerator = new JsonSchemaGenerator(schemaGeneratorSettings); var schemaResolver = new SwaggerSchemaResolver(document, schemaGeneratorSettings); var context = new AspNetCoreOperationProcessorContext( document, operationDescription, GetType(), GetType().GetMethod(nameof(SomeAction), BindingFlags.NonPublic | BindingFlags.Instance), new SwaggerGenerator(schemaGenerator, schemaGeneratorSettings, schemaResolver), schemaGenerator, schemaResolver, swaggerSettings, new List <SwaggerOperationDescription>()) { ApiDescription = apiDescription, }; return(context); }
private async Task <string> FromAssemblyTypeAsync(string[] classNames, string settingsData) { var document = new SwaggerDocument(); var settings = JsonConvert.DeserializeObject <AssemblyTypeToSwaggerGeneratorSettings>(settingsData); RegisterReferencePaths(GetAllReferencePaths(settings)); var generator = new JsonSchemaGenerator(settings); var schemaResolver = new SwaggerSchemaResolver(document, settings); #if FullNet var assemblies = PathUtilities.ExpandFileWildcards(settings.AssemblySettings.AssemblyPaths) .Select(path => Assembly.LoadFrom(path)).ToArray(); #else var currentDirectory = await DynamicApis.DirectoryGetCurrentDirectoryAsync().ConfigureAwait(false); var assemblies = PathUtilities.ExpandFileWildcards(settings.AssemblySettings.AssemblyPaths) .Select(path => Context.LoadFromAssemblyPath(PathUtilities.MakeAbsolutePath(path, currentDirectory))).ToArray(); #endif var allExportedClassNames = assemblies.SelectMany(a => a.ExportedTypes).Select(t => t.FullName).ToList(); var matchedClassNames = classNames .SelectMany(n => PathUtilities.FindWildcardMatches(n, allExportedClassNames, '.')) .Distinct(); foreach (var className in matchedClassNames) { var type = assemblies.Select(a => a.GetType(className)).FirstOrDefault(t => t != null); await generator.GenerateAsync(type, schemaResolver).ConfigureAwait(false); } return(document.ToJson()); }
/// <summary>Generates a Swagger specification for the given <see cref="ApiDescriptionGroupCollection"/>.</summary> /// <param name="apiDescriptionGroups"><see cref="ApiDescriptionGroup"/>.</param> /// <returns>The <see cref="SwaggerDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <SwaggerDocument> GenerateAsync(ApiDescriptionGroupCollection apiDescriptionGroups) { var apiDescriptions = apiDescriptionGroups.Items.SelectMany(g => g.Items); var document = await CreateDocumentAsync(apiDescriptionGroups).ConfigureAwait(false); var schemaResolver = new SwaggerSchemaResolver(document, Settings); var apiGroups = apiDescriptions.Where(apiDescription => apiDescription.ActionDescriptor is ControllerActionDescriptor) .Select(apiDescription => new Tuple <ApiDescription, MethodInfo>(apiDescription, ((ControllerActionDescriptor)apiDescription.ActionDescriptor).MethodInfo)) .GroupBy(item => item.Item2.DeclaringType); foreach (var controllerApiDescriptionGroup in apiGroups) { await GenerateForControllerAsync(document, controllerApiDescriptionGroup.Key, controllerApiDescriptionGroup, new SwaggerGenerator(_schemaGenerator, Settings, schemaResolver), schemaResolver).ConfigureAwait(false); } document.GenerateOperationIds(); var controllerTypes = apiGroups.Select(k => k.Key); foreach (var processor in Settings.DocumentProcessors) { await processor.ProcessAsync(new DocumentProcessorContext(document, controllerTypes, schemaResolver, _schemaGenerator, Settings)); } return(document); }
async Task <string> GetSwaggerWay2() { var document = new SwaggerDocument(); var Settings = new JsonSchemaGeneratorSettings() { SchemaType = SchemaType.Swagger2, }; var generator = new JsonSchemaGenerator(Settings); var schemaResolver = new SwaggerSchemaResolver(document, Settings); var loadedAssemblies = LoadDtoAssemblies(); foreach (var dtoAsm in loadedAssemblies.Dto) { var models = dtoAsm.Assembly.GetTypes() .Where(x => x.Namespace.StartsWith(dtoAsm.ProjectName + ".Public")); foreach (var model in models) { await generator.GenerateAsync(model, schemaResolver).ConfigureAwait(false); } /* * //this swagger.json will be wrong (paths and controller is not detected) * var controllers = dtoAsm.Assembly.GetTypes() * .Where(x => x.Name.EndsWith("Controller")); * * foreach (var controller in controllers) * { * await generator.GenerateAsync(controller, schemaResolver).ConfigureAwait(false); * } */ } //File.WriteAllText(Path.Combine(outputPath, "swagger.json"), document.ToJson()); var tsGenerator = new SwaggerToTypeScriptClientGenerator(document, new SwaggerToTypeScriptClientGeneratorSettings { ClassName = "{controller}Client", }); var tsModels = tsGenerator.GenerateFile(); return(tsModels); }
/// <summary>Generates a Swagger specification for the given controller types.</summary> /// <param name="controllerTypes">The types of the controller.</param> /// <returns>The <see cref="SwaggerDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public SwaggerDocument GenerateForControllers(IEnumerable <Type> controllerTypes) { var document = CreateDocument(Settings); var schemaResolver = new SwaggerSchemaResolver(document, Settings); foreach (var controllerType in controllerTypes) { GenerateForController(document, controllerType, new SwaggerGenerator(_schemaGenerator, Settings, schemaResolver)); } document.GenerateOperationIds(); foreach (var processor in Settings.DocumentProcessors) { processor.Process(new DocumentProcessorContext(document, controllerTypes, schemaResolver, _schemaGenerator)); } return(document); }
/// <summary>Generates a Swagger specification for the given controller types.</summary> /// <param name="controllerTypes">The types of the controller.</param> /// <returns>The <see cref="SwaggerDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <SwaggerDocument> GenerateForControllersAsync(IEnumerable <Type> controllerTypes) { var document = await CreateDocumentAsync(Settings).ConfigureAwait(false); var schemaResolver = new SwaggerSchemaResolver(document, Settings); foreach (var controllerType in controllerTypes) { await GenerateForControllerAsync(document, controllerType, new SwaggerGenerator(_schemaGenerator, Settings, schemaResolver), schemaResolver).ConfigureAwait(false); } document.GenerateOperationIds(); foreach (var processor in Settings.DocumentProcessors) { await processor.ProcessAsync(new DocumentProcessorContext(document, controllerTypes, schemaResolver, _schemaGenerator)); } return(document); }
private async Task <List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> > > AddOperationDescriptionsToDocumentAsync( SwaggerDocument document, Type controllerType, List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> > operations, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var addedOperations = new List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> >(); var allOperations = operations.Select(t => t.Item1).ToList(); foreach (var tuple in operations) { var operation = tuple.Item1; var apiDescription = tuple.Item2; var method = tuple.Item3; var addOperation = await RunOperationProcessorsAsync(document, apiDescription, controllerType, method, operation, allOperations, swaggerGenerator, schemaResolver).ConfigureAwait(false); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new SwaggerPathItem(); } if (document.Paths[path].ContainsKey(operation.Method)) { throw new InvalidOperationException($"The method '{operation.Method}' on path '{path}' is registered multiple times."); } document.Paths[path][operation.Method] = operation.Operation; addedOperations.Add(tuple); } } return(addedOperations); }
internal string FromAssemblyType(string[] classNames, string settingsData) { var document = new SwaggerDocument(); var settings = JsonConvert.DeserializeObject<AssemblyTypeToSwaggerGeneratorSettings>(settingsData); RegisterReferencePaths(GetAllReferencePaths(settings)); var generator = new JsonSchemaGenerator(settings); var schemaResolver = new SwaggerSchemaResolver(document, settings); #if FullNet var assembly = Assembly.LoadFrom(settings.AssemblyPath); #else var assembly = Context.LoadFromAssemblyPath(settings.AssemblyPath); #endif foreach (var className in classNames) { var type = assembly.GetType(className); var schema = generator.Generate(type, schemaResolver); document.Definitions[type.Name] = schema; } return document.ToJson(); }
/// <summary>Generates a Swagger specification for the given <see cref="ApiDescriptionGroupCollection"/>.</summary> /// <param name="apiDescriptionGroups"><see cref="ApiDescriptionGroup"/>.</param> /// <returns>The <see cref="SwaggerDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <SwaggerDocument> GenerateAsync(ApiDescriptionGroupCollection apiDescriptionGroups) { var apiDescriptions = apiDescriptionGroups.Items.SelectMany(g => g.Items); var document = await CreateDocumentAsync().ConfigureAwait(false); var schemaResolver = new SwaggerSchemaResolver(document, Settings); var apiGroups = apiDescriptions.Where(apiDescription => apiDescription.ActionDescriptor is ControllerActionDescriptor) .Select(apiDescription => new Tuple <ApiDescription, ControllerActionDescriptor>(apiDescription, (ControllerActionDescriptor)apiDescription.ActionDescriptor)) .GroupBy(item => item.Item2.ControllerTypeInfo.AsType()) .ToArray(); var usedControllerTypes = new List <Type>(); foreach (var controllerApiDescriptionGroup in apiGroups) { var generator = new SwaggerGenerator(_schemaGenerator, Settings, schemaResolver); var isIncluded = await GenerateForControllerAsync(document, controllerApiDescriptionGroup.Key, controllerApiDescriptionGroup, generator, schemaResolver).ConfigureAwait(false); if (isIncluded) { usedControllerTypes.Add(controllerApiDescriptionGroup.Key); } } document.GenerateOperationIds(); var controllerTypes = apiGroups.Select(k => k.Key).ToArray(); foreach (var processor in Settings.DocumentProcessors) { await processor.ProcessAsync(new DocumentProcessorContext(document, controllerTypes, usedControllerTypes, schemaResolver, _schemaGenerator, Settings)); } return(document); }
internal string FromAssemblyType(string[] classNames, string settingsData) { var document = new SwaggerDocument(); var settings = JsonConvert.DeserializeObject <AssemblyTypeToSwaggerGeneratorSettings>(settingsData); RegisterReferencePaths(GetAllReferencePaths(settings)); var generator = new JsonSchemaGenerator(settings); var schemaResolver = new SwaggerSchemaResolver(document, settings); #if FullNet var assembly = Assembly.LoadFrom(settings.AssemblyPath); #else var assembly = Context.LoadFromAssemblyPath(settings.AssemblyPath); #endif foreach (var className in classNames) { var type = assembly.GetType(className); var schema = generator.Generate(type, schemaResolver); document.Definitions[type.Name] = schema; } return(document.ToJson()); }
private async Task <List <Type> > GenerateForControllersAsync( SwaggerDocument document, IGrouping <Type, Tuple <ApiDescription, ControllerActionDescriptor> >[] apiGroups, SwaggerSchemaResolver schemaResolver) { var usedControllerTypes = new List <Type>(); var swaggerGenerator = new SwaggerGenerator(_schemaGenerator, Settings, schemaResolver); var allOperations = new List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> >(); foreach (var controllerApiDescriptionGroup in apiGroups) { var controllerType = controllerApiDescriptionGroup.Key; var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (!hasIgnoreAttribute) { var operations = new List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> >(); foreach (var item in controllerApiDescriptionGroup) { var apiDescription = item.Item1; var method = item.Item2.MethodInfo; var actionHasIgnoreAttribute = method.GetCustomAttributes().Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (actionHasIgnoreAttribute) { continue; } var path = apiDescription.RelativePath; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var controllerActionDescriptor = (ControllerActionDescriptor)apiDescription.ActionDescriptor; var httpMethod = apiDescription.HttpMethod?.ToLowerInvariant() ?? SwaggerOperationMethod.Get; var operationDescription = new SwaggerOperationDescription { Path = path, Method = httpMethod, Operation = new SwaggerOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, controllerActionDescriptor, method), Consumes = apiDescription.SupportedRequestFormats .Select(f => f.MediaType) .Distinct() .ToList(), Produces = apiDescription.SupportedResponseTypes .SelectMany(t => t.ApiResponseFormats.Select(f => f.MediaType)) .Distinct() .ToList() } }; operations.Add(new Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo>(operationDescription, apiDescription, method)); } var addedOperations = await AddOperationDescriptionsToDocumentAsync(document, controllerType, operations, swaggerGenerator, schemaResolver).ConfigureAwait(false); if (addedOperations.Any()) { usedControllerTypes.Add(controllerApiDescriptionGroup.Key); } allOperations.AddRange(addedOperations); } } UpdateConsumesAndProduces(document, allOperations); return(usedControllerTypes); }
private async Task GenerateForControllerAsync(SwaggerDocument document, Type controllerType, IEnumerable <Tuple <ApiDescription, MethodInfo> > controllerApiDescriptionGroup, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (hasIgnoreAttribute) { return; } var operations = new List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> >(); var descriptions = new List <SwaggerOperationDescription>(); foreach (var item in controllerApiDescriptionGroup) { var apiDescription = item.Item1; var method = item.Item2; var actionHasIgnoreAttribute = method.GetCustomAttributes().Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (actionHasIgnoreAttribute) { continue; } var path = apiDescription.RelativePath; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var controllerActionDescriptor = (ControllerActionDescriptor)apiDescription.ActionDescriptor; if (!Enum.TryParse <SwaggerOperationMethod>(apiDescription.HttpMethod, ignoreCase: true, result: out var swaggerOperationMethod)) { swaggerOperationMethod = SwaggerOperationMethod.Undefined; } var operationDescription = new SwaggerOperationDescription { Path = path, Method = swaggerOperationMethod, Operation = new SwaggerOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, controllerActionDescriptor, method) } }; operations.Add(new Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo>(operationDescription, apiDescription, method)); } await AddOperationDescriptionsToDocumentAsync(document, controllerType, operations, swaggerGenerator, schemaResolver).ConfigureAwait(false); }
private async Task AddOperationDescriptionsToDocumentAsync(SwaggerDocument document, Type controllerType, List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo> > operations, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var allOperation = operations.Select(t => t.Item1).ToList(); foreach (var tuple in operations) { var operation = tuple.Item1; var apiDescription = tuple.Item2; var method = tuple.Item3; for (var i = 0; i < apiDescription.SupportedRequestFormats.Count; i++) { var mediaType = apiDescription.SupportedRequestFormats[i].MediaType; if (document.Consumes == null) { document.Consumes = new List <string>(); } if (!document.Consumes.Contains(mediaType, StringComparer.OrdinalIgnoreCase)) { document.Consumes.Add(mediaType); } } var addOperation = await RunOperationProcessorsAsync(document, apiDescription, controllerType, method, operation, allOperation, swaggerGenerator, schemaResolver).ConfigureAwait(false); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new SwaggerPathItem(); } if (document.Paths[path].ContainsKey(operation.Method)) { throw new InvalidOperationException($"The method '{operation.Method}' on path '{path}' is registered multiple times."); } document.Paths[path][operation.Method] = operation.Operation; } } }
private async Task <bool> RunOperationProcessorsAsync(SwaggerDocument document, ApiDescription apiDescription, Type controllerType, MethodInfo methodInfo, SwaggerOperationDescription operationDescription, List <SwaggerOperationDescription> allOperations, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { // 1. Run from settings var operationProcessorContext = new AspNetCoreOperationProcessorContext(document, operationDescription, controllerType, methodInfo, swaggerGenerator, _schemaGenerator, schemaResolver, Settings, allOperations) { ApiDescription = apiDescription, }; foreach (var operationProcessor in Settings.OperationProcessors) { if (await operationProcessor.ProcessAsync(operationProcessorContext).ConfigureAwait(false) == false) { return(false); } } // 2. Run from class attributes var operationProcessorAttribute = methodInfo.DeclaringType.GetTypeInfo() .GetCustomAttributes() // 3. Run from method attributes .Concat(methodInfo.GetCustomAttributes()) .Where(a => a.GetType().IsAssignableTo("SwaggerOperationProcessorAttribute", TypeNameStyle.Name)); foreach (dynamic attribute in operationProcessorAttribute) { var operationProcessor = ReflectionExtensions.HasProperty(attribute, "Parameters") ? (IOperationProcessor)Activator.CreateInstance(attribute.Type, attribute.Parameters) : (IOperationProcessor)Activator.CreateInstance(attribute.Type); if (await operationProcessor.ProcessAsync(operationProcessorContext) == false) { return(false); } } return(true); }
/// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> private async Task GenerateForControllerAsync(SwaggerDocument document, Type controllerType, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (!hasIgnoreAttribute) { var operations = new List <Tuple <SwaggerOperationDescription, MethodInfo> >(); foreach (var method in GetActionMethods(controllerType)) { var httpPaths = GetHttpPaths(controllerType, method).ToList(); var httpMethods = GetSupportedHttpMethods(method).ToList(); foreach (var httpPath in httpPaths) { foreach (var httpMethod in httpMethods) { var operationDescription = new SwaggerOperationDescription { Path = httpPath, Method = httpMethod, Operation = new SwaggerOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, controllerType.Name, method) } }; operations.Add(new Tuple <SwaggerOperationDescription, MethodInfo>(operationDescription, method)); } } } await AddOperationDescriptionsToDocumentAsync(document, controllerType, operations, swaggerGenerator, schemaResolver).ConfigureAwait(false); } }
private async Task <bool> GenerateForControllerAsync(SwaggerDocument document, Type controllerType, IEnumerable <Tuple <ApiDescription, ControllerActionDescriptor> > controllerApiDescriptionGroup, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (hasIgnoreAttribute) { return(false); } var operations = new List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo, IEnumerable <string>, IEnumerable <string> > >(); foreach (var item in controllerApiDescriptionGroup) { var apiDescription = item.Item1; var method = item.Item2.MethodInfo; var actionHasIgnoreAttribute = method.GetCustomAttributes().Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (actionHasIgnoreAttribute) { continue; } var path = apiDescription.RelativePath; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var controllerActionDescriptor = (ControllerActionDescriptor)apiDescription.ActionDescriptor; var httpMethod = apiDescription.HttpMethod?.ToLowerInvariant() ?? SwaggerOperationMethod.Get; var operationDescription = new SwaggerOperationDescription { Path = path, Method = httpMethod, Operation = new SwaggerOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, controllerActionDescriptor, method) } }; var consumes = apiDescription.SupportedRequestFormats .Select(f => f.MediaType) .Distinct(); var produces = apiDescription.SupportedResponseTypes .SelectMany(t => t.ApiResponseFormats.Select(f => f.MediaType)) .Distinct(); operations.Add(new Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo, IEnumerable <string>, IEnumerable <string> >( operationDescription, apiDescription, method, consumes, produces)); } return(await AddOperationDescriptionsToDocumentAsync(document, controllerType, operations, swaggerGenerator, schemaResolver).ConfigureAwait(false)); }
private async Task <bool> AddOperationDescriptionsToDocumentAsync(SwaggerDocument document, Type controllerType, List <Tuple <SwaggerOperationDescription, ApiDescription, MethodInfo, IEnumerable <string>, IEnumerable <string> > > operations, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var globalConsumes = operations .SelectMany(o => o.Item4) .Where(c => operations.All(o => o.Item4.Count() == 0 || o.Item4.Contains(c))) .Distinct(); if (globalConsumes.Any()) { document.Consumes = globalConsumes.ToList(); } var globalProduces = operations .SelectMany(o => o.Item5) .Where(c => operations.All(o => o.Item5.Count() == 0 || o.Item5.Contains(c))) .Distinct(); if (globalProduces.Any()) { document.Produces = globalProduces.ToList(); } var addedOperations = 0; var allOperation = operations.Select(t => t.Item1).ToList(); foreach (var tuple in operations) { var operation = tuple.Item1; var apiDescription = tuple.Item2; var method = tuple.Item3; var consumes = tuple.Item4; if (consumes.Any(c => !globalConsumes.Contains(c))) { operation.Operation.Consumes = consumes.ToList(); } var produces = tuple.Item5; if (produces.Any(c => !globalProduces.Contains(c))) { operation.Operation.Produces = produces.ToList(); } var addOperation = await RunOperationProcessorsAsync(document, apiDescription, controllerType, method, operation, allOperation, swaggerGenerator, schemaResolver).ConfigureAwait(false); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new SwaggerPathItem(); } if (document.Paths[path].ContainsKey(operation.Method)) { throw new InvalidOperationException($"The method '{operation.Method}' on path '{path}' is registered multiple times."); } document.Paths[path][operation.Method] = operation.Operation; addedOperations++; } } return(addedOperations > 0); }
private async Task <bool> AddOperationDescriptionsToDocumentAsync(SwaggerDocument document, Type controllerType, List <Tuple <SwaggerOperationDescription, MethodInfo> > operations, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var addedOperations = 0; var allOperation = operations.Select(t => t.Item1).ToList(); foreach (var tuple in operations) { var operation = tuple.Item1; var method = tuple.Item2; var addOperation = await RunOperationProcessorsAsync(document, controllerType, method, operation, allOperation, swaggerGenerator, schemaResolver).ConfigureAwait(false); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new SwaggerPathItem(); } if (document.Paths[path].ContainsKey(operation.Method)) { throw new InvalidOperationException("The method '" + operation.Method + "' on path '" + path + "' is registered multiple times " + "(check the DefaultUrlTemplate setting [default for Web API: 'api/{controller}/{id}'; for MVC projects: '{controller}/{action}/{id?}'])."); } document.Paths[path][operation.Method] = operation.Operation; addedOperations++; } } return(addedOperations > 0); }
/// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> private async Task <bool> GenerateForControllerAsync(SwaggerDocument document, Type controllerType, SwaggerGenerator swaggerGenerator, SwaggerSchemaResolver schemaResolver) { var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"); if (hasIgnoreAttribute) { return(false); } var operations = new List <Tuple <SwaggerOperationDescription, MethodInfo> >(); var currentControllerType = controllerType; while (currentControllerType != null) { foreach (var method in GetActionMethods(currentControllerType)) { var httpPaths = GetHttpPaths(controllerType, method).ToList(); var httpMethods = GetSupportedHttpMethods(method).ToList(); foreach (var httpPath in httpPaths) { foreach (var httpMethod in httpMethods) { var isPathAlreadyDefinedInInheritanceHierarchy = operations.Any(o => o.Item1.Path == httpPath && o.Item1.Method == httpMethod && o.Item2.DeclaringType != currentControllerType && o.Item2.DeclaringType.IsAssignableTo(currentControllerType.FullName, TypeNameStyle.FullName)); if (isPathAlreadyDefinedInInheritanceHierarchy == false) { var operationDescription = new SwaggerOperationDescription { Path = httpPath, Method = httpMethod, Operation = new SwaggerOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, controllerType.Name, method) } }; operations.Add(new Tuple <SwaggerOperationDescription, MethodInfo>(operationDescription, method)); } } } } currentControllerType = currentControllerType.GetTypeInfo().BaseType; } return(await AddOperationDescriptionsToDocumentAsync(document, controllerType, operations, swaggerGenerator, schemaResolver).ConfigureAwait(false)); }