private AspNetCoreOperationProcessorContext GetContext(ApiDescription apiDescription) { var operationDescription = new OpenApiOperationDescription { Operation = new OpenApiOperation() }; var swaggerSettings = new AspNetCoreOpenApiDocumentGeneratorSettings(); var document = new OpenApiDocument(); var schemaGeneratorSettings = new OpenApiDocumentGeneratorSettings(); var schemaGenerator = new OpenApiSchemaGenerator(schemaGeneratorSettings); var schemaResolver = new OpenApiSchemaResolver(document, schemaGeneratorSettings); swaggerSettings.SchemaGenerator = schemaGenerator; var context = new AspNetCoreOperationProcessorContext( document, operationDescription, GetType(), GetType().GetMethod(nameof(SomeAction), BindingFlags.NonPublic | BindingFlags.Instance), new OpenApiDocumentGenerator(swaggerSettings, schemaResolver), schemaGenerator, schemaResolver, swaggerSettings, new List <OpenApiOperationDescription>()) { ApiDescription = apiDescription, }; return(context); }
/// <summary>Generates a Swagger specification for the given <see cref="ApiDescriptionGroupCollection"/>.</summary> /// <param name="apiDescriptionGroups">The <see cref="ApiDescriptionGroupCollection"/>.</param> /// <returns>The <see cref="OpenApiDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <OpenApiDocument> 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 OpenApiSchemaResolver(document, Settings); var apiGroups = apiDescriptions .Select(apiDescription => new Tuple <ApiDescription, ControllerActionDescriptor>(apiDescription, (ControllerActionDescriptor)apiDescription.ActionDescriptor)) .GroupBy(item => item.Item2.ControllerTypeInfo.AsType()) .ToArray(); var usedControllerTypes = GenerateForControllers(document, apiGroups, schemaResolver); document.GenerateOperationIds(); var controllerTypes = apiGroups.Select(k => k.Key).ToArray(); foreach (var processor in Settings.DocumentProcessors) { processor.Process(new DocumentProcessorContext(document, controllerTypes, usedControllerTypes, schemaResolver, Settings.SchemaGenerator, Settings)); } Settings.PostProcess?.Invoke(document); return(document); }
/// <summary> /// Generates Swagger document for the specified Azure Function classes, including only the listed Functions. /// </summary> /// <param name="azureFunctionClassTypes">The Azure Function classes (static classes)</param> /// <param name="functionNames">The function names (defined by FunctionNameAttribute)</param> /// <returns>The generated Swagger document</returns> public async Task <OpenApiDocument> GenerateForAzureFunctionClassesAsync(IEnumerable <Type> azureFunctionClassTypes, IList <string> functionNames) { var document = await CreateDocumentAsync().ConfigureAwait(false); var schemaResolver = new OpenApiSchemaResolver(document, Settings); var usedAzureFunctionClassTypes = new List <Type>(); foreach (var azureFunctionClassType in azureFunctionClassTypes) { var generator = new OpenApiDocumentGenerator(Settings, schemaResolver); var isIncluded = await GenerateForAzureFunctionClassAsync(document, azureFunctionClassType, generator, schemaResolver, functionNames); if (isIncluded) { usedAzureFunctionClassTypes.Add(azureFunctionClassType); } } document.GenerateOperationIds(); foreach (var processor in Settings.DocumentProcessors) { processor.Process(new DocumentProcessorContext(document, azureFunctionClassTypes, usedAzureFunctionClassTypes, schemaResolver, Settings.SchemaGenerator, Settings)); } 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="OpenApiDocument" />.</returns> /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception> public async Task <OpenApiDocument> GenerateForControllersAsync(IEnumerable <Type> controllerTypes) { var document = await CreateDocumentAsync().ConfigureAwait(false); var schemaResolver = new OpenApiSchemaResolver(document, Settings); var usedControllerTypes = new List <Type>(); foreach (var controllerType in controllerTypes) { var generator = new OpenApiDocumentGenerator(Settings, schemaResolver); var isIncluded = GenerateForController(document, controllerType, generator, schemaResolver); if (isIncluded) { usedControllerTypes.Add(controllerType); } } document.GenerateOperationIds(); foreach (var processor in Settings.DocumentProcessors) { processor.Process(new DocumentProcessorContext(document, controllerTypes, usedControllerTypes, schemaResolver, Settings.SchemaGenerator, Settings)); } return(document); }
public void When_generating_multiple_types_then_they_are_appended_to_the_definitions() { //// Arrange var classNames = new[] { "NSwag.Generation.WebApi.Tests.B", "NSwag.Generation.WebApi.Tests.C" }; //// Act var document = new OpenApiDocument(); var settings = new JsonSchemaGeneratorSettings(); var schemaResolver = new OpenApiSchemaResolver(document, settings); var generator = new JsonSchemaGenerator(settings); foreach (var className in classNames) { var type = typeof(TypesToSwaggerTests).Assembly.GetType(className); generator.Generate(type, schemaResolver); } 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 OpenApiDocument(); var generator = new JsonSchemaGenerator(Settings); var schemaResolver = new OpenApiSchemaResolver(document, Settings); #if FullNet var assemblies = PathUtilities.ExpandFileWildcards(AssemblyPaths) .Select(path => Assembly.LoadFrom(path)).ToArray(); #else var currentDirectory = DynamicApis.DirectoryGetCurrentDirectory(); 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); generator.Generate(type, schemaResolver); } return(document.ToJson(OutputType)); }
public async Task <OpenApiDocument> GenerateDocument(Assembly assembly) { var document = await CreateDocumentAsync().ConfigureAwait(false); var schemaResolver = new OpenApiSchemaResolver(document, Settings); var handlerTypes = GetAllHandlerTypes(assembly); var usedHandlerTypes = new List <Type>(); foreach (var handlerType in handlerTypes) { var generator = new OpenApiDocumentGenerator(Settings, schemaResolver); var isIncluded = GenerateForHandler(document, handlerType, generator, schemaResolver); if (isIncluded) { usedHandlerTypes.Add(handlerType); } } document.GenerateOperationIds(); foreach (var processor in Settings.DocumentProcessors) { processor.Process(new DocumentProcessorContext(document, handlerTypes, usedHandlerTypes, schemaResolver, Settings.SchemaGenerator, Settings)); } return(document); }
internal Builder(IAppEntity app, OpenApiDocument document, OpenApiSchemaResolver schemaResolver, OpenApiSchemaGenerator schemaGenerator) { Document = document; AppName = app.Name; ChangeStatusSchema = schemaGenerator.GenerateWithReference <JsonSchema>(typeof(ChangeStatusDto).ToContextualType(), schemaResolver); }
private static List <OpenApiDocument> GetOpenApiDocumentSepareted(JsonSchemaGeneratorSettings settings, Assembly[] assemblies, List <string> classNames) { List <OpenApiDocument> result = new List <OpenApiDocument>(); foreach (var className in classNames) { var document = new OpenApiDocument(); var generator = new JsonSchemaGenerator(settings); var schemaResolver = new OpenApiSchemaResolver(document, settings); var type = assemblies.Select(a => a.GetType(className)).FirstOrDefault(t => t != null); generator.Generate(type, schemaResolver); result.Add(document); } return(result); }
public async Task <OpenApiDocument> GenerateAsync(HttpContext httpContext, IAppEntity app, IEnumerable <ISchemaEntity> schemas, bool flat) { var document = CreateApiDocument(httpContext, app); var schemaResolver = new OpenApiSchemaResolver(document, schemaSettings); requestCache.AddDependency(app.UniqueId, app.Version); foreach (var schema in schemas) { requestCache.AddDependency(schema.UniqueId, schema.Version); } var builder = new Builder(app, document, schemaResolver, schemaGenerator); var validSchemas = schemas.Where(x => x.SchemaDef.IsPublished && x.SchemaDef.Type != SchemaDefType.Component && x.SchemaDef.Fields.Count > 0); var partitionResolver = app.PartitionResolver(); foreach (var schema in validSchemas) { var components = await appProvider.GetComponentsAsync(schema, httpContext.RequestAborted); GenerateSchemaOperations(builder.Schema(schema.SchemaDef, partitionResolver, components, flat)); } GenerateSharedOperations(builder.Shared()); var context = new DocumentProcessorContext(document, Enumerable.Empty <Type>(), Enumerable.Empty <Type>(), schemaResolver, schemaGenerator, schemaSettings); foreach (var processor in schemaSettings.DocumentProcessors) { processor.Process(context); } return(document); }
private List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> > AddOperationDescriptionsToDocument( OpenApiDocument document, Type controllerType, List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> > operations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver) { var addedOperations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >(); var allOperations = new List <OpenApiOperationDescription>(operations.Count); allOperations.AddRange(operations.Select(t => t.Item1)); foreach (var tuple in operations) { var operation = tuple.Item1; var apiDescription = tuple.Item2; var method = tuple.Item3; var addOperation = RunOperationProcessors( document, apiDescription, controllerType, method, operation, allOperations, swaggerGenerator, schemaResolver); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.TryGetValue(path, out var pathItem)) { document.Paths[path] = pathItem = new OpenApiPathItem(); } if (pathItem.ContainsKey(operation.Method)) { throw new InvalidOperationException($"The method '{operation.Method}' on path '{path}' is registered multiple times."); } pathItem[operation.Method] = operation.Operation; addedOperations.Add(tuple); } } return(addedOperations); }
private static OpenApiDocument GetOpenApiDocument(JsonSchemaGeneratorSettings settings, Assembly[] assemblies, List <string> classNames) { var document = new OpenApiDocument(); var generator = new JsonSchemaGenerator(settings); var schemaResolver = new OpenApiSchemaResolver(document, settings); //IEnumerable<string> matchedClassNames = ClassNames // .SelectMany(n => PathUtilities.FindWildcardMatches(n, allExportedClassNames, '.')) // .Distinct(); foreach (var className in classNames) { var type = assemblies.Select(a => a.GetType(className)).FirstOrDefault(t => t != null); generator.Generate(type, schemaResolver); } //SchemaType outputType = SchemaType.Swagger2; //return document.ToJson(outputType); return(document); }
public OpenApiDocument Generate(HttpContext httpContext, IAppEntity app, IEnumerable <ISchemaEntity> schemas, bool flat = false) { var document = CreateApiDocument(httpContext, app); var schemaResolver = new OpenApiSchemaResolver(document, schemaSettings); requestCache.AddDependency(app.UniqueId, app.Version); var builder = new Builder( app, document, schemaResolver, schemaGenerator); foreach (var schema in schemas.Where(x => x.SchemaDef.IsPublished)) { requestCache.AddDependency(schema.UniqueId, schema.Version); GenerateSchemaOperations(builder.Schema(schema.SchemaDef, flat)); } GenerateSharedOperations(builder.Shared()); var context = new DocumentProcessorContext(document, Enumerable.Empty <Type>(), Enumerable.Empty <Type>(), schemaResolver, schemaGenerator, schemaSettings); foreach (var processor in schemaSettings.DocumentProcessors) { processor.Process(context); } return(document); }
// TODO: remove asyncness as most NSwag operations have been converted to sync. private async Task <bool> RunOperationProcessorsAsync(OpenApiDocument document, Type staticAzureFunctionClassType, MethodInfo methodInfo, OpenApiOperationDescription operationDescription, List <OpenApiOperationDescription> allOperations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver) { var context = new OperationProcessorContext(document, operationDescription, staticAzureFunctionClassType, methodInfo, swaggerGenerator, Settings.SchemaGenerator, schemaResolver, Settings, allOperations); // 1. Run from settings foreach (var operationProcessor in Settings.OperationProcessors) { if (operationProcessor.Process(context) == 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().IsAssignableToTypeName("SwaggerOperationProcessorAttribute", TypeNameStyle.Name)); foreach (dynamic attribute in operationProcessorAttribute) { var operationProcessor = ObjectExtensions.HasProperty(attribute, "Parameters") ? (IOperationProcessor)Activator.CreateInstance(attribute.Type, attribute.Parameters) : (IOperationProcessor)Activator.CreateInstance(attribute.Type); if (operationProcessor.Process(context) == false) { return(false); } } return(true); }
private async Task <bool> AddOperationDescriptionsToDocumentAsync(OpenApiDocument document, Type staticAzureFunctionClassType, List <Tuple <OpenApiOperationDescription, MethodInfo> > operations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver) { var addedOperations = 0; var allOps = operations.Select(t => t.Item1).ToList(); foreach (var o in operations) { var operation = o.Item1; var method = o.Item2; var addOperation = await RunOperationProcessorsAsync(document, staticAzureFunctionClassType, method, operation, allOps, swaggerGenerator, schemaResolver); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new OpenApiPathItem(); } 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> GenerateForAzureFunctionClassAsync(OpenApiDocument document, Type staticAzureFunctionClassType, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver, IList <string> functionNames) { var operations = new List <Tuple <OpenApiOperationDescription, MethodInfo> >(); foreach (var method in GetActionMethods(staticAzureFunctionClassType, functionNames)) { var httpPaths = GetHttpPaths(method); var httpMethods = GetSupportedHttpMethods(method); foreach (var httpPath in httpPaths) { foreach (var httpMethod in httpMethods) { var operationDescription = new OpenApiOperationDescription { Path = httpPath, Method = httpMethod, Operation = new OpenApiOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, staticAzureFunctionClassType.Name, method) } }; operations.Add(new Tuple <OpenApiOperationDescription, MethodInfo>(operationDescription, method)); } } } return(await AddOperationDescriptionsToDocumentAsync(document, staticAzureFunctionClassType, operations, swaggerGenerator, schemaResolver)); }
private List <Type> GenerateForControllers( OpenApiDocument document, IGrouping <Type, Tuple <ApiDescription, ControllerActionDescriptor> >[] apiGroups, OpenApiSchemaResolver schemaResolver) { var usedControllerTypes = new List <Type>(); var swaggerGenerator = new OpenApiDocumentGenerator(Settings, schemaResolver); var allOperations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >(); foreach (var controllerApiDescriptionGroup in apiGroups) { var controllerType = controllerApiDescriptionGroup.Key; var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name) .Any(); if (!hasIgnoreAttribute) { var operations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >(); foreach (var item in controllerApiDescriptionGroup) { var apiDescription = item.Item1; var method = item.Item2.MethodInfo; var actionHasIgnoreAttribute = method.GetCustomAttributes().GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name).Any(); if (actionHasIgnoreAttribute) { continue; } var path = apiDescription.RelativePath; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var controllerActionDescriptor = (ControllerActionDescriptor)apiDescription.ActionDescriptor; var httpMethod = apiDescription.HttpMethod?.ToLowerInvariant() ?? OpenApiOperationMethod.Get; var operationDescription = new OpenApiOperationDescription { Path = path, Method = httpMethod, Operation = new OpenApiOperation { 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 <OpenApiOperationDescription, ApiDescription, MethodInfo>(operationDescription, apiDescription, method)); } var addedOperations = AddOperationDescriptionsToDocument(document, controllerType, operations, swaggerGenerator, schemaResolver); if (addedOperations.Any()) { usedControllerTypes.Add(controllerApiDescriptionGroup.Key); } allOperations.AddRange(addedOperations); } } UpdateConsumesAndProduces(document, allOperations); return(usedControllerTypes); }
private bool AddOperationDescriptionsToDocument(OpenApiDocument document, Type controllerType, List <Tuple <OpenApiOperationDescription, MethodInfo> > operations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver 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 = RunOperationProcessors(document, controllerType, method, operation, allOperation, swaggerGenerator, schemaResolver); if (addOperation) { var path = operation.Path.Replace("//", "/"); // iiQ Custom // .. Prevents "The method 'get' on path '/v1.0' is registered multiple times" exception // .. Also guards for root pathed URLs such as "/v1.0" since all URLs are versioned in iiQ if (path.Split(new char[] { '/' }).Length <= 2) { continue; } if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new OpenApiPathItem(); } 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 bool GenerateForController(OpenApiDocument document, Type controllerType, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver) { var hasIgnoreAttribute = controllerType.GetTypeInfo() .GetCustomAttributes() .GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name) .Any(); if (hasIgnoreAttribute) { return(false); } var operations = new List <Tuple <OpenApiOperationDescription, 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.IsAssignableToTypeName(currentControllerType.FullName, TypeNameStyle.FullName)); if (isPathAlreadyDefinedInInheritanceHierarchy == false) { var operationDescription = new OpenApiOperationDescription { Path = httpPath, Method = httpMethod, Operation = new OpenApiOperation { IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, controllerType.Name, method, httpMethod) } }; operations.Add(new Tuple <OpenApiOperationDescription, MethodInfo>(operationDescription, method)); } } } } currentControllerType = currentControllerType.GetTypeInfo().BaseType; } return(AddOperationDescriptionsToDocument(document, controllerType, operations, swaggerGenerator, schemaResolver)); }
private List <Type> GenerateApiGroups( OpenApiDocument document, IGrouping <Type, Tuple <ApiDescription, ActionDescriptor> >[] apiGroups, OpenApiSchemaResolver schemaResolver) { var usedControllerTypes = new List <Type>(); var swaggerGenerator = new OpenApiDocumentGenerator(Settings, schemaResolver); var allOperations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >(); foreach (var apiGroup in apiGroups) { var controllerType = apiGroup.Key; var hasIgnoreAttribute = controllerType != null && controllerType .GetTypeInfo() .GetCustomAttributes() .GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name) .Any(); if (!hasIgnoreAttribute) { var operations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >(); foreach (var item in apiGroup) { var apiDescription = item.Item1; if (apiDescription.RelativePath == null) { continue; } var method = (item.Item2 as ControllerActionDescriptor)?.MethodInfo; if (method != null) { var actionHasIgnoreAttribute = method.GetCustomAttributes().GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name).Any(); if (actionHasIgnoreAttribute) { continue; } } var path = apiDescription.RelativePath; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var httpMethod = apiDescription.HttpMethod?.ToLowerInvariant() ?? (apiDescription.ParameterDescriptions.Where(p => { return(p.Source == Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource.Body); }).Count() > 0 ? OpenApiOperationMethod.Post : OpenApiOperationMethod.Get); var operationDescription = new OpenApiOperationDescription { Path = path, Method = httpMethod, Operation = new OpenApiOperation { IsDeprecated = IsOperationDeprecated(item.Item1, apiDescription.ActionDescriptor, method), OperationId = GetOperationId(document, apiDescription, method, httpMethod), 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 <OpenApiOperationDescription, ApiDescription, MethodInfo>(operationDescription, apiDescription, method)); } var addedOperations = AddOperationDescriptionsToDocument(document, controllerType, operations, swaggerGenerator, schemaResolver); if (addedOperations.Any() && apiGroup.Key != null) { usedControllerTypes.Add(apiGroup.Key); } allOperations.AddRange(addedOperations); } } UpdateConsumesAndProduces(document, allOperations); return(usedControllerTypes); }
private bool AddOperationDescriptionsToDocument(OpenApiDocument document, Type controllerType, List <Tuple <OpenApiOperationDescription, MethodInfo> > operations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver 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 = RunOperationProcessors(document, controllerType, method, operation, allOperation, swaggerGenerator, schemaResolver); if (addOperation) { var path = operation.Path.Replace("//", "/"); if (!document.Paths.ContainsKey(path)) { document.Paths[path] = new OpenApiPathItem(); } 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); }
private bool GenerateForHandler(OpenApiDocument document, Type handlerType, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver) { var methodInfo = handlerType.GetMethod("Handle"); var isQuery = handlerType.IsAssignableToGenericType(typeof(IQueryRequestHandler <,>)); var httpMethod = isQuery ? OpenApiOperationMethod.Get : OpenApiOperationMethod.Post; var httpPath = $"/rpc/{GetRequestTypeFullName(methodInfo)}"; var operationDescription = new OpenApiOperationDescription { Path = httpPath, Method = httpMethod, Operation = new OpenApiOperation { IsDeprecated = methodInfo.GetCustomAttribute <ObsoleteAttribute>() != null, OperationId = GetOperationId(document, handlerType.Name) } }; return(AddOperationDescriptionsToDocumentAsync(document, handlerType, (operationDescription, methodInfo), swaggerGenerator, schemaResolver)); }