示例#1
0
        private async Task <bool> TryAddFileParameterAsync(
            OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter)
        {
            var typeInfo = _settings.ReflectionService.GetDescription(extendedApiParameter.ParameterType, extendedApiParameter.Attributes, _settings);

            var isFileArray = IsFileArray(extendedApiParameter.ApiParameter.Type, typeInfo);

            var attributes = extendedApiParameter.Attributes
                             .Union(extendedApiParameter.ParameterType.GetTypeInfo().GetCustomAttributes());

            var hasSwaggerFileAttribute = attributes.Any(a =>
                                                         a.GetType().IsAssignableTo("SwaggerFileAttribute", TypeNameStyle.Name));

            if (typeInfo.Type == JsonObjectType.File ||
                typeInfo.Format == JsonFormatStrings.Binary ||
                hasSwaggerFileAttribute ||
                isFileArray)
            {
                await AddFileParameterAsync(context, extendedApiParameter, isFileArray).ConfigureAwait(false);

                return(true);
            }

            return(false);
        }
        private async Task AddFileParameterAsync(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, bool isFileArray)
        {
            var operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

            InitializeFileParameter(operationParameter, isFileArray);

            context.OperationDescription.Operation.Parameters.Add(operationParameter);
        }
示例#3
0
        private void AddFileParameter(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, bool isFileArray)
        {
            var operationParameter = CreatePrimitiveParameter(context, extendedApiParameter);

            InitializeFileParameter(operationParameter, isFileArray);

            context.OperationDescription.Operation.Parameters.Add(operationParameter);
        }
        private OpenApiParameter CreatePrimitiveParameter(
            OperationProcessorContext context,
            ExtendedApiParameterDescription extendedApiParameter)
        {
            var contextualParameterType = extendedApiParameter.ParameterType
                                          .ToContextualType(extendedApiParameter.Attributes);

            var description        = extendedApiParameter.GetDocumentation();
            var operationParameter = context.DocumentGenerator.CreatePrimitiveParameter(
                extendedApiParameter.ApiParameter.Name, description, contextualParameterType);

            var exampleValue = extendedApiParameter.PropertyInfo != null?
                               context.SchemaGenerator.GenerateExample(extendedApiParameter.PropertyInfo.ToContextualAccessor()) : null;

            var hasExampleValue = exampleValue != null;
            var hasDefaultValue = extendedApiParameter.ParameterInfo?.HasDefaultValue == true;

            if (hasExampleValue || hasDefaultValue)
            {
                var defaultValue = hasDefaultValue ? context.SchemaGenerator
                                   .ConvertDefaultValue(contextualParameterType, extendedApiParameter.ParameterInfo.DefaultValue) : null;

                if (_settings.SchemaType == SchemaType.Swagger2)
                {
                    operationParameter.Default = defaultValue;
                    operationParameter.Example = exampleValue;
                }
                else if (operationParameter.Schema.HasReference)
                {
                    if (_settings.AllowReferencesWithProperties)
                    {
                        operationParameter.Schema = new JsonSchema
                        {
                            Default   = defaultValue,
                            Example   = exampleValue,
                            Reference = operationParameter.Schema,
                        };
                    }
                    else
                    {
                        operationParameter.Schema = new JsonSchema
                        {
                            Default = defaultValue,
                            Example = exampleValue,
                            OneOf   = { operationParameter.Schema },
                        };
                    }
                }
                else
                {
                    operationParameter.Schema.Default = defaultValue;
                    operationParameter.Schema.Example = exampleValue;
                }
            }

            operationParameter.IsRequired = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault);
            return(operationParameter);
        }
示例#5
0
        private async Task AddBodyParameterAsync(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter)
        {
            var operation     = context.OperationDescription.Operation;
            var parameterType = extendedApiParameter.ApiParameter.Type;

            if (parameterType.Name == "XmlDocument" || parameterType.InheritsFrom("XmlDocument", TypeNameStyle.Name))
            {
                operation.Consumes = new List <string> {
                    "application/xml"
                };
                operation.Parameters.Add(new SwaggerParameter
                {
                    Name   = extendedApiParameter.ApiParameter.Name,
                    Kind   = SwaggerParameterKind.Body,
                    Schema = new JsonSchema4 {
                        Type = JsonObjectType.String
                    },
                    IsNullableRaw = true,
                    IsRequired    = true,
                    Description   = await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false)
                });
            }
            else if (parameterType.IsAssignableTo("System.IO.Stream", TypeNameStyle.FullName))
            {
                operation.Consumes = new List <string> {
                    "application/octet-stream"
                };
                operation.Parameters.Add(new SwaggerParameter
                {
                    Name   = extendedApiParameter.ApiParameter.Name,
                    Kind   = SwaggerParameterKind.Body,
                    Schema = new JsonSchema4 {
                        Type = JsonObjectType.String, Format = JsonFormatStrings.Byte
                    },
                    IsNullableRaw = true,
                    IsRequired    = true,
                    Description   = await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false)
                });
            }
            else
            {
                var typeDescription = _settings.ReflectionService.GetDescription(extendedApiParameter.ApiParameter.Type, extendedApiParameter.Attributes, _settings);

                var operationParameter = new SwaggerParameter
                {
                    Name          = extendedApiParameter.ApiParameter.Name,
                    Kind          = SwaggerParameterKind.Body,
                    IsRequired    = true, // FromBody parameters are always required.
                    IsNullableRaw = typeDescription.IsNullable,
                    Description   = await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false),
                    Schema        = await context.SchemaGenerator.GenerateWithReferenceAndNullability <JsonSchema4>(
                        extendedApiParameter.ApiParameter.Type, extendedApiParameter.Attributes, isNullable : false, schemaResolver : context.SchemaResolver).ConfigureAwait(false)
                };

                operation.Parameters.Add(operationParameter);
            }
        }
        private async Task <SwaggerParameter> CreatePrimitiveParameterAsync(
            OperationProcessorContext context,
            ExtendedApiParameterDescription extendedApiParameter)
        {
            var operationParameter = await context.SwaggerGenerator.CreatePrimitiveParameterAsync(
                extendedApiParameter.ApiParameter.Name,
                await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false),
                extendedApiParameter.ParameterType,
                extendedApiParameter.Attributes).ConfigureAwait(false);

            if (extendedApiParameter.ParameterInfo?.HasDefaultValue == true)
            {
                operationParameter.Default = extendedApiParameter.ParameterInfo.DefaultValue;
            }

            operationParameter.IsRequired = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault);
            return(operationParameter);
        }
示例#7
0
        private async Task AddFileParameterAsync(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, bool isFileArray)
        {
            var parameterDocumentation = string.Empty;

            if (extendedApiParameter.ParameterInfo != null)
            {
                parameterDocumentation = await extendedApiParameter.ParameterInfo.GetDescriptionAsync(extendedApiParameter.Attributes).ConfigureAwait(false);
            }
            else if (extendedApiParameter.PropertyInfo != null)
            {
                parameterDocumentation = await extendedApiParameter.PropertyInfo.GetDescriptionAsync(extendedApiParameter.Attributes).ConfigureAwait(false);
            }

            var operationParameter = await CreatePrimitiveParameterAsync(
                context, extendedApiParameter).ConfigureAwait(false);

            InitializeFileParameter(operationParameter, isFileArray);
            context.OperationDescription.Operation.Parameters.Add(operationParameter);
        }
        private void AddFileParameter(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, bool isFileArray)
        {
            if (_settings.SchemaType == SchemaType.Swagger2)
            {
                var operationParameter = CreatePrimitiveParameter(context, extendedApiParameter);
                operationParameter.Type = JsonObjectType.File;
                operationParameter.Kind = OpenApiParameterKind.FormData;

                if (isFileArray)
                {
                    operationParameter.CollectionFormat = OpenApiParameterCollectionFormat.Multi;
                }

                context.OperationDescription.Operation.Parameters.Add(operationParameter);
            }
            else
            {
                var schema = CreateOrGetFormDataSchema(context);
                schema.Properties[extendedApiParameter.ApiParameter.Name] = CreateFormDataProperty(context, extendedApiParameter, schema);
            }
        }
示例#9
0
        private bool TryAddFileParameter(
            OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter)
        {
            var typeInfo = _settings.ReflectionService.GetDescription(extendedApiParameter.ParameterType.ToContextualType(extendedApiParameter.Attributes), _settings);

            var isFileArray = IsFileArray(extendedApiParameter.ApiParameter.Type, typeInfo);

            var attributes = extendedApiParameter.Attributes
                             .Union(extendedApiParameter.ParameterType.GetTypeInfo().GetCustomAttributes());

            var hasSwaggerFileAttribute = attributes.FirstAssignableToTypeNameOrDefault("SwaggerFileAttribute", TypeNameStyle.Name) != null;

            if (typeInfo.Type == JsonObjectType.File ||
                typeInfo.Format == JsonFormatStrings.Binary ||
                hasSwaggerFileAttribute ||
                isFileArray)
            {
                AddFileParameter(context, extendedApiParameter, isFileArray);
                return(true);
            }

            return(false);
        }
示例#10
0
        private OpenApiParameter CreatePrimitiveParameter(
            OperationProcessorContext context,
            ExtendedApiParameterDescription extendedApiParameter)
        {
            var contextualParameter = extendedApiParameter.ParameterType.ToContextualType(extendedApiParameter.Attributes);

            var description        = extendedApiParameter.GetDocumentation();
            var operationParameter = context.DocumentGenerator.CreatePrimitiveParameter(
                extendedApiParameter.ApiParameter.Name, description, contextualParameter);

            if (extendedApiParameter.ParameterInfo?.HasDefaultValue == true)
            {
                var defaultValue = context.SchemaGenerator
                                   .ConvertDefaultValue(contextualParameter, extendedApiParameter.ParameterInfo.DefaultValue);

                if (_settings.SchemaType == SchemaType.Swagger2)
                {
                    operationParameter.Default = defaultValue;
                }
                else if (operationParameter.Schema.HasReference)
                {
                    operationParameter.Schema = new JsonSchema
                    {
                        Default = defaultValue,
                        OneOf   = { operationParameter.Schema }
                    };
                }
                else
                {
                    operationParameter.Schema.Default = defaultValue;
                }
            }

            operationParameter.IsRequired = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault);
            return(operationParameter);
        }
        /// <summary>Processes the specified method information.</summary>
        /// <param name="operationProcessorContext"></param>
        /// <returns>true if the operation should be added to the Swagger specification.</returns>
        public async Task <bool> ProcessAsync(OperationProcessorContext operationProcessorContext)
        {
            if (!(operationProcessorContext is AspNetCoreOperationProcessorContext context))
            {
                return(false);
            }

            var httpPath   = context.OperationDescription.Path;
            var parameters = context.ApiDescription.ParameterDescriptions;

            var methodParameters = context.MethodInfo.GetParameters();

            var position = 1;

            foreach (var apiParameter in parameters.Where(p => p.Source != null))
            {
                // TODO: Provide extension point so that this can be implemented in the ApiVersionProcessor class
                var versionProcessor = _settings.OperationProcessors.TryGet <ApiVersionProcessor>();
                if (versionProcessor != null &&
                    versionProcessor.IgnoreParameter &&
                    apiParameter.ModelMetadata?.DataTypeName == "ApiVersion")
                {
                    continue;
                }

                var parameterDescriptor = apiParameter.TryGetPropertyValue <ParameterDescriptor>("ParameterDescriptor");
                var parameterName       = parameterDescriptor?.Name ?? apiParameter.Name;

                // In Mvc < 2.0, there isn't a good way to infer the attributes of a parameter with a IModelNameProvider.Name
                // value that's different than the parameter name. Additionally, ApiExplorer will recurse in to complex model bound types
                // and expose properties as top level parameters. Consequently, determining the property or parameter of an Api is best
                // effort attempt.
                var extendedApiParameter = new ExtendedApiParameterDescription
                {
                    ApiParameter  = apiParameter,
                    Attributes    = Enumerable.Empty <Attribute>(),
                    ParameterType = apiParameter.Type
                };

                var parameter = methodParameters.FirstOrDefault(m => m.Name == parameterName);
                if (parameter != null)
                {
                    extendedApiParameter.ParameterInfo = parameter;
                    extendedApiParameter.Attributes    = parameter.GetCustomAttributes();
                }
                else
                {
                    var property = operationProcessorContext.ControllerType.GetProperty(parameterName, BindingFlags.Public | BindingFlags.Instance);
                    if (property != null)
                    {
                        extendedApiParameter.PropertyInfo = property;
                        extendedApiParameter.Attributes   = property.GetCustomAttributes();
                    }
                }

                if (apiParameter.Type == null)
                {
                    extendedApiParameter.ParameterType = typeof(string);

                    if (apiParameter.Source == BindingSource.Path)
                    {
                        // ignore unused implicit path parameters
                        if (!httpPath.ToLowerInvariant().Contains("{" + apiParameter.Name.ToLowerInvariant() + ":") &&
                            !httpPath.ToLowerInvariant().Contains("{" + apiParameter.Name.ToLowerInvariant() + "}"))
                        {
                            continue;
                        }

                        extendedApiParameter.Attributes = extendedApiParameter.Attributes.Concat(new[] { new NotNullAttribute() });
                    }
                }

                if (extendedApiParameter.Attributes.Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"))
                {
                    continue;
                }

                SwaggerParameter operationParameter = null;
                if (apiParameter.Source == BindingSource.Path)
                {
                    operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind       = SwaggerParameterKind.Path;
                    operationParameter.IsRequired = true; // apiParameter.RouteInfo?.IsOptional == false;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Header)
                {
                    operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind = SwaggerParameterKind.Header;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Query)
                {
                    operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind = SwaggerParameterKind.Query;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Body)
                {
                    operationParameter = await AddBodyParameterAsync(context, extendedApiParameter).ConfigureAwait(false);
                }
                else if (apiParameter.Source == BindingSource.Form)
                {
                    operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind = SwaggerParameterKind.FormData;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else
                {
                    if (await TryAddFileParameterAsync(context, extendedApiParameter).ConfigureAwait(false) == false)
                    {
                        operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                        operationParameter.Kind = SwaggerParameterKind.Query;

                        context.OperationDescription.Operation.Parameters.Add(operationParameter);
                    }
                }

                if (parameter != null && operationParameter != null)
                {
                    if (_settings.SchemaType == SchemaType.OpenApi3)
                    {
                        operationParameter.IsNullableRaw = null;
                    }

                    operationParameter.Position = position;
                    ((Dictionary <ParameterInfo, SwaggerParameter>)operationProcessorContext.Parameters)[parameter] = operationParameter;
                    position++;
                }
            }

            RemoveUnusedPathParameters(context.OperationDescription, httpPath);
            UpdateConsumedTypes(context.OperationDescription);

            EnsureSingleBodyParameter(context.OperationDescription);

            return(true);
        }
示例#12
0
        private OpenApiParameter AddBodyParameter(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter)
        {
            OpenApiParameter operationParameter;

            var contextualParameterType = extendedApiParameter.ParameterType
                                          .ToContextualType(extendedApiParameter.Attributes);

            var typeDescription = _settings.ReflectionService.GetDescription(contextualParameterType, _settings);
            var isNullable      = _settings.AllowNullableBodyParameters && typeDescription.IsNullable;
            var operation       = context.OperationDescription.Operation;

            var parameterType = extendedApiParameter.ParameterType;

            if (parameterType.Name == "XmlDocument" || parameterType.InheritsFromTypeName("XmlDocument", TypeNameStyle.Name))
            {
                operation.TryAddConsumes("application/xml");
                operationParameter = new OpenApiParameter
                {
                    Name   = extendedApiParameter.ApiParameter.Name,
                    Kind   = OpenApiParameterKind.Body,
                    Schema = new JsonSchema
                    {
                        Type          = JsonObjectType.String,
                        IsNullableRaw = isNullable
                    },
                    IsNullableRaw = isNullable,
                    IsRequired    = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault),
                    Description   = extendedApiParameter.GetDocumentation()
                };
            }
            else if (parameterType.IsAssignableToTypeName("System.IO.Stream", TypeNameStyle.FullName))
            {
                operation.TryAddConsumes("application/octet-stream");
                operationParameter = new OpenApiParameter
                {
                    Name   = extendedApiParameter.ApiParameter.Name,
                    Kind   = OpenApiParameterKind.Body,
                    Schema = new JsonSchema
                    {
                        Type          = JsonObjectType.String,
                        Format        = JsonFormatStrings.Byte,
                        IsNullableRaw = isNullable
                    },
                    IsNullableRaw = isNullable,
                    IsRequired    = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault),
                    Description   = extendedApiParameter.GetDocumentation()
                };
            }
            else // body from type
            {
                operationParameter = new OpenApiParameter
                {
                    Name          = extendedApiParameter.ApiParameter.Name,
                    Kind          = OpenApiParameterKind.Body,
                    IsRequired    = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault),
                    IsNullableRaw = isNullable,
                    Description   = extendedApiParameter.GetDocumentation(),
                    Schema        = context.SchemaGenerator.GenerateWithReferenceAndNullability <JsonSchema>(
                        contextualParameterType, isNullable, schemaResolver: context.SchemaResolver)
                };
            }

            operation.Parameters.Add(operationParameter);
            return(operationParameter);
        }
示例#13
0
 private static JsonSchemaProperty CreateFormDataProperty(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, JsonSchema schema)
 {
     return(context.SchemaGenerator.GenerateWithReferenceAndNullability <JsonSchemaProperty>(
                extendedApiParameter.ApiParameter.Type.ToContextualType(extendedApiParameter.Attributes), context.SchemaResolver));
 }
示例#14
0
        /// <summary>Processes the specified method information.</summary>
        /// <param name="operationProcessorContext"></param>
        /// <returns>true if the operation should be added to the Swagger specification.</returns>
        public async Task <bool> ProcessAsync(OperationProcessorContext operationProcessorContext)
        {
            if (!(operationProcessorContext is AspNetCoreOperationProcessorContext context))
            {
                return(false);
            }

            var httpPath   = context.OperationDescription.Path;
            var parameters = context.ApiDescription.ParameterDescriptions;

            var methodParameters = context.MethodInfo.GetParameters();

            foreach (var apiParameter in parameters.Where(p => p.Source != null))
            {
                var parameterDescriptor = apiParameter.TryGetPropertyValue <ParameterDescriptor>("ParameterDescriptor");
                var parameterName       = parameterDescriptor?.Name ?? apiParameter.Name;

                // In Mvc < 2.0, there isn't a good way to infer the attributes of a parameter with a IModelNameProvider.Name
                // value that's different than the parameter name. Additionally, ApiExplorer will recurse in to complex model bound types
                // and expose properties as top level parameters. Consequently, determining the property or parameter of an Api is best
                // effort attempt.
                var extendedApiParameter = new ExtendedApiParameterDescription
                {
                    ApiParameter = apiParameter,
                    Attributes   = Enumerable.Empty <Attribute>(),
                };

                var parameter = methodParameters.FirstOrDefault(m => m.Name == parameterName);
                if (parameter != null)
                {
                    extendedApiParameter.ParameterInfo = parameter;
                    extendedApiParameter.Attributes    = parameter.GetCustomAttributes();
                }
                else
                {
                    var property = operationProcessorContext.ControllerType.GetProperty(parameterName, BindingFlags.Public | BindingFlags.Instance);
                    if (property != null)
                    {
                        extendedApiParameter.PropertyInfo = property;
                        extendedApiParameter.Attributes   = property.GetCustomAttributes();
                    }
                }

                if (extendedApiParameter.Attributes.Any(a => a.GetType().Name == "SwaggerIgnoreAttribute"))
                {
                    continue;
                }

                if (apiParameter.Source == BindingSource.Path)
                {
                    var operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind       = SwaggerParameterKind.Path;
                    operationParameter.IsRequired = true; // Path is always required => property not needed

                    if (_settings.SchemaType == SchemaType.Swagger2)
                    {
                        operationParameter.IsNullableRaw = false;
                    }

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Header)
                {
                    var operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind = SwaggerParameterKind.Header;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Query)
                {
                    var operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind = SwaggerParameterKind.Query;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Body)
                {
                    await AddBodyParameterAsync(context, extendedApiParameter).ConfigureAwait(false);
                }
                else if (apiParameter.Source == BindingSource.Form)
                {
                    var operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                    operationParameter.Kind = SwaggerParameterKind.FormData;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else
                {
                    if (await TryAddFileParameterAsync(context, extendedApiParameter).ConfigureAwait(false) == false)
                    {
                        var operationParameter = await CreatePrimitiveParameterAsync(context, extendedApiParameter).ConfigureAwait(false);

                        operationParameter.Kind = SwaggerParameterKind.Query;

                        context.OperationDescription.Operation.Parameters.Add(operationParameter);
                    }
                }
            }

            RemoveUnusedPathParameters(context.OperationDescription, httpPath);
            UpdateConsumedTypes(context.OperationDescription);

            EnsureSingleBodyParameter(context.OperationDescription);

            return(true);
        }
示例#15
0
        private async Task <SwaggerParameter> AddBodyParameterAsync(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter)
        {
            SwaggerParameter operationParameter;

            var typeDescription = _settings.ReflectionService.GetDescription(
                extendedApiParameter.ParameterType, extendedApiParameter.Attributes, _settings);
            var isNullable = _settings.AllowNullableBodyParameters && typeDescription.IsNullable;

            var operation     = context.OperationDescription.Operation;
            var parameterType = extendedApiParameter.ParameterType;

            if (parameterType.Name == "XmlDocument" || parameterType.InheritsFrom("XmlDocument", TypeNameStyle.Name))
            {
                operation.Consumes = new List <string> {
                    "application/xml"
                };
                operationParameter = new SwaggerParameter
                {
                    Name   = extendedApiParameter.ApiParameter.Name,
                    Kind   = SwaggerParameterKind.Body,
                    Schema = new JsonSchema4
                    {
                        Type          = JsonObjectType.String,
                        IsNullableRaw = isNullable
                    },
                    IsNullableRaw = isNullable,
                    IsRequired    = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault),
                    Description   = await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false)
                };
            }
            else if (parameterType.IsAssignableTo("System.IO.Stream", TypeNameStyle.FullName))
            {
                operation.Consumes = new List <string> {
                    "application/octet-stream"
                };
                operationParameter = new SwaggerParameter
                {
                    Name   = extendedApiParameter.ApiParameter.Name,
                    Kind   = SwaggerParameterKind.Body,
                    Schema = new JsonSchema4
                    {
                        Type          = JsonObjectType.String,
                        Format        = JsonFormatStrings.Byte,
                        IsNullableRaw = isNullable
                    },
                    IsNullableRaw = isNullable,
                    IsRequired    = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault),
                    Description   = await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false)
                };
            }
            else // body from type
            {
                operationParameter = new SwaggerParameter
                {
                    Name          = extendedApiParameter.ApiParameter.Name,
                    Kind          = SwaggerParameterKind.Body,
                    IsRequired    = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault),
                    IsNullableRaw = isNullable,
                    Description   = await extendedApiParameter.GetDocumentationAsync().ConfigureAwait(false),
                    Schema        = await context.SchemaGenerator.GenerateWithReferenceAndNullabilityAsync <JsonSchema4>(
                        extendedApiParameter.ParameterType, extendedApiParameter.Attributes, isNullable, schemaResolver : context.SchemaResolver).ConfigureAwait(false)
                };
            }

            operation.Parameters.Add(operationParameter);
            return(operationParameter);
        }
示例#16
0
        /// <summary>Processes the specified method information.</summary>
        /// <param name="operationProcessorContext"></param>
        /// <returns>true if the operation should be added to the Swagger specification.</returns>
        public bool Process(OperationProcessorContext operationProcessorContext)
        {
            if (!(operationProcessorContext is AspNetCoreOperationProcessorContext context))
            {
                return(false);
            }

            var httpPath         = context.OperationDescription.Path;
            var parameters       = context.ApiDescription.ParameterDescriptions;
            var methodParameters = context.MethodInfo?.GetParameters() ?? new ParameterInfo[0];

            var position = 1;

            foreach (var apiParameter in parameters.Where(p => p.Source != null))
            {
                // TODO: Provide extension point so that this can be implemented in the ApiVersionProcessor class
                var versionProcessor = _settings.OperationProcessors.TryGet <ApiVersionProcessor>();
                if (versionProcessor != null &&
                    versionProcessor.IgnoreParameter &&
                    apiParameter.ModelMetadata?.DataTypeName == "ApiVersion")
                {
                    continue;
                }

                // In Mvc < 2.0, there isn't a good way to infer the attributes of a parameter with a IModelNameProvider.Name
                // value that's different than the parameter name. Additionally, ApiExplorer will recurse in to complex model bound types
                // and expose properties as top level parameters. Consequently, determining the property or parameter of an Api is best
                // effort attempt.
                var extendedApiParameter = new ExtendedApiParameterDescription(_settings)
                {
                    ApiParameter  = apiParameter,
                    Attributes    = Enumerable.Empty <Attribute>(),
                    ParameterType = apiParameter.Type
                };

                ParameterInfo parameter = null;

                var propertyName = apiParameter.ModelMetadata?.PropertyName;
                var property     = !string.IsNullOrEmpty(propertyName) ?
                                   apiParameter.ModelMetadata.ContainerType?.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance) :
                                   null;

                if (property != null)
                {
                    extendedApiParameter.PropertyInfo = property;
                    extendedApiParameter.Attributes   = property.GetCustomAttributes();
                }
                else
                {
                    var parameterDescriptor = apiParameter.TryGetPropertyValue <ParameterDescriptor>("ParameterDescriptor");
                    var parameterName       = parameterDescriptor?.Name ?? apiParameter.Name;
                    parameter = methodParameters.FirstOrDefault(m => m.Name.ToLowerInvariant() == parameterName.ToLowerInvariant());
                    if (parameter != null)
                    {
                        extendedApiParameter.ParameterInfo = parameter;
                        extendedApiParameter.Attributes    = parameter.GetCustomAttributes();
                    }
                    else if (operationProcessorContext.ControllerType != null)
                    {
                        parameterName = apiParameter.Name;
                        property      = operationProcessorContext.ControllerType.GetProperty(parameterName, BindingFlags.Public | BindingFlags.Instance);
                        if (property != null)
                        {
                            extendedApiParameter.PropertyInfo = property;
                            extendedApiParameter.Attributes   = property.GetCustomAttributes();
                        }
                    }
                }

                if (apiParameter.Type == null)
                {
                    extendedApiParameter.ParameterType = typeof(string);

                    if (apiParameter.Source == BindingSource.Path)
                    {
                        // ignore unused implicit path parameters
                        if (!httpPath.ToLowerInvariant().Contains("{" + apiParameter.Name.ToLowerInvariant() + ":") &&
                            !httpPath.ToLowerInvariant().Contains("{" + apiParameter.Name.ToLowerInvariant() + "}"))
                        {
                            continue;
                        }

                        extendedApiParameter.Attributes = extendedApiParameter.Attributes.Concat(new[] { new NotNullAttribute() });
                    }
                }

                if (extendedApiParameter.Attributes.GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name).Any())
                {
                    continue;
                }

                OpenApiParameter operationParameter = null;
                if (apiParameter.Source == BindingSource.Path ||
                    (apiParameter.Source == BindingSource.Custom &&
                     httpPath.Contains($"{{{apiParameter.Name}}}")))
                {
                    operationParameter            = CreatePrimitiveParameter(context, extendedApiParameter);
                    operationParameter.Kind       = OpenApiParameterKind.Path;
                    operationParameter.IsRequired = true; // apiParameter.RouteInfo?.IsOptional == false;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Header)
                {
                    operationParameter      = CreatePrimitiveParameter(context, extendedApiParameter);
                    operationParameter.Kind = OpenApiParameterKind.Header;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Query)
                {
                    operationParameter      = CreatePrimitiveParameter(context, extendedApiParameter);
                    operationParameter.Kind = OpenApiParameterKind.Query;

                    context.OperationDescription.Operation.Parameters.Add(operationParameter);
                }
                else if (apiParameter.Source == BindingSource.Body)
                {
                    operationParameter = AddBodyParameter(context, extendedApiParameter);
                }
                else if (apiParameter.Source == BindingSource.Form)
                {
                    if (_settings.SchemaType == SchemaType.Swagger2)
                    {
                        operationParameter      = CreatePrimitiveParameter(context, extendedApiParameter);
                        operationParameter.Kind = OpenApiParameterKind.FormData;
                        context.OperationDescription.Operation.Parameters.Add(operationParameter);
                    }
                    else
                    {
                        var schema = CreateOrGetFormDataSchema(context);
                        schema.Properties[extendedApiParameter.ApiParameter.Name] = CreateFormDataProperty(context, extendedApiParameter, schema);
                    }
                }
                else
                {
                    if (TryAddFileParameter(context, extendedApiParameter) == false)
                    {
                        operationParameter      = CreatePrimitiveParameter(context, extendedApiParameter);
                        operationParameter.Kind = OpenApiParameterKind.Query;

                        context.OperationDescription.Operation.Parameters.Add(operationParameter);
                    }
                }

                if (operationParameter != null)
                {
                    operationParameter.Position = position;
                    position++;

                    if (_settings.SchemaType == SchemaType.OpenApi3)
                    {
                        operationParameter.IsNullableRaw = null;
                    }

                    if (parameter != null)
                    {
                        if (_settings.GenerateOriginalParameterNames && operationParameter.Name != parameter.Name)
                        {
                            operationParameter.OriginalName = parameter.Name;
                        }

                        ((Dictionary <ParameterInfo, OpenApiParameter>)operationProcessorContext.Parameters)[parameter] = operationParameter;
                    }
                }
            }

            ApplyOpenApiBodyParameterAttribute(context.OperationDescription, context.MethodInfo);
            RemoveUnusedPathParameters(context.OperationDescription, httpPath);
            UpdateConsumedTypes(context.OperationDescription);
            EnsureSingleBodyParameter(context.OperationDescription);

            return(true);
        }