Example #1
0
        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);
        }
Example #4
0
        /// <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);
        }
Example #6
0
            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);
        }
Example #8
0
    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);
    }
Example #9
0
        /// <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);
        }
Example #10
0
        /// <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);
        }
Example #11
0
        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);
        }
Example #14
0
            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());
            }
Example #15
0
        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);
            }
        }
Example #20
0
        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));
        }
Example #21
0
        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);
        }
Example #22
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);
        }
Example #23
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));
        }