示例#1
0
        OpenApiSchema GetOverrideType(
            ISchemaGenerator generator,
            SchemaRepository repository,
            IReadOnlyList <Type> types,
            IReadOnlyList <object?>?examples)
        {
            if (types.Count == 1)
            {
                return(generator.GenerateSchema(types.Single(), repository));
            }
            else
            {
                var union = new OpenApiSchema();

                for (var i = 0; i < types.Count; i++)
                {
                    var schema  = generator.GenerateSchema(types[i], repository);
                    var example = (examples != null) ? examples[i] : null;

                    if (example != null)
                    {
                        schema.Example = OpenApiAnyFactory.CreateFor(schema, example);
                    }

                    union.OneOf.Add(schema);
                }

                return(union);
            }
        }
示例#2
0
        public override OpenApiSchema CreateSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!(_contractResolver.ResolveContract(type) is JsonDictionaryContract jsonDictionaryContract))
            {
                throw new InvalidOperationException($"Type {type} does not resolve to a JsonDictionaryContract");
            }

            var keyType   = jsonDictionaryContract.DictionaryKeyType ?? typeof(object);
            var valueType = jsonDictionaryContract.DictionaryValueType ?? typeof(object);

            if (keyType.IsEnum)
            {
                // This is a special case where we can include named properties based on the enum values
                return(new OpenApiSchema
                {
                    Type = "object",
                    Properties = keyType.GetEnumNames()
                                 .ToDictionary(
                        name => name,
                        name => _schemaGenerator.GenerateSchema(valueType, schemaRepository)
                        )
                });
            }

            return(new OpenApiSchema
            {
                Type = "object",
                AdditionalPropertiesAllowed = true,
                AdditionalProperties = _schemaGenerator.GenerateSchema(valueType, schemaRepository)
            });
        }
示例#3
0
        public override OpenApiSchema CreateSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!type.IsDictionary(out Type keyType, out Type valueType))
            {
                throw new InvalidOperationException($"Type {type} is not a dictionary");
            }

            if (keyType.IsEnum)
            {
                // This is a special case where we can include named properties based on the enum values
                return(new OpenApiSchema
                {
                    Type = "object",
                    Properties = keyType.GetEnumNames()
                                 .ToDictionary(
                        name => name,
                        name => _schemaGenerator.GenerateSchema(valueType, schemaRepository)
                        )
                });
            }

            return(new OpenApiSchema
            {
                Type = "object",
                AdditionalPropertiesAllowed = true,
                AdditionalProperties = _schemaGenerator.GenerateSchema(valueType, schemaRepository)
            });
        }
示例#4
0
        private OpenApiParameter GenerateParameter(
            ApiParameterDescription apiParameter,
            SchemaRepository schemaRepository)
        {
            var name = _options.DescribeAllParametersInCamelCase
                ? apiParameter.Name.ToCamelCase()
                : apiParameter.Name;

            var location = (apiParameter.Source != null && ParameterLocationMap.ContainsKey(apiParameter.Source))
                ? ParameterLocationMap[apiParameter.Source]
                : ParameterLocation.Query;

            var isRequired = (apiParameter.IsFromPath()) ||
                             apiParameter.CustomAttributes().Any(attr => RequiredAttributeTypes.Contains(attr.GetType()));

            var schema = (apiParameter.ModelMetadata != null)
                ? _schemaGenerator.GenerateSchema(apiParameter.ModelMetadata.ModelType, schemaRepository)
                : new OpenApiSchema {
                Type = "string"
            };

            // If it's NOT a reference schema, apply contextual metadata (i.e. from custom attributes)
            if (schema.Reference == null)
            {
                // Honor default value for optional action parameters
                var parameterInfo = apiParameter.ParameterInfo();
                if (parameterInfo != null && parameterInfo.HasDefaultValue)
                {
                    schema.Default = OpenApiAnyFactory.TryCreateFor(schema, parameterInfo.DefaultValue, out IOpenApiAny openApiAny)
                        ? openApiAny
                        : null;
                }

                schema.ApplyCustomAttributes(apiParameter.CustomAttributes());
            }

            var parameter = new OpenApiParameter
            {
                Name     = name,
                In       = location,
                Required = isRequired,
                Schema   = schema
            };

            var filterContext = new ParameterFilterContext(
                apiParameter,
                _schemaGenerator,
                schemaRepository,
                apiParameter.ParameterInfo(),
                apiParameter.PropertyInfo());

            foreach (var filter in _options.ParameterFilters)
            {
                filter.Apply(parameter, filterContext);
            }

            return(parameter);
        }
 private OpenApiSchema CreatePolymorphicSchema(IEnumerable <Type> knownSubTypes, SchemaRepository schemaRepository)
 {
     return(new OpenApiSchema
     {
         OneOf = knownSubTypes
                 .Select(subType => _schemaGenerator.GenerateSchema(subType, schemaRepository))
                 .ToList()
     });
 }
        private OpenApiParameter GenerateParameter(
            ApiDescription apiDescription,
            ApiParameterDescription apiParameter,
            SchemaRepository schemaRepository)
        {
            apiParameter.GetAdditionalMetadata(
                apiDescription,
                out ParameterInfo parameterInfo,
                out PropertyInfo propertyInfo,
                out IEnumerable <object> parameterOrPropertyAttributes);

            var name = _options.DescribeAllParametersInCamelCase
                ? apiParameter.Name.ToCamelCase()
                : apiParameter.Name;

            var location = ParameterLocationMap.ContainsKey(apiParameter.Source)
                ? ParameterLocationMap[apiParameter.Source]
                : ParameterLocation.Query;

            var isRequired = (apiParameter.IsFromPath()) ||
                             parameterOrPropertyAttributes.Any(attr => RequiredAttributeTypes.Contains(attr.GetType()));

            var defaultValue = parameterInfo?.DefaultValue
                               ?? parameterOrPropertyAttributes.OfType <DefaultValueAttribute>().FirstOrDefault()?.Value;

            var schema = (apiParameter.ModelMetadata != null)
                ? _schemaGenerator.GenerateSchema(apiParameter.Type, schemaRepository)
                : new OpenApiSchema {
                Type = "string"
            };

            if (defaultValue != null && schema.Reference == null)
            {
                schema.Default = OpenApiAnyFactory.TryCreateFor(schema, defaultValue, out IOpenApiAny openApiAny)
                    ? openApiAny
                    : null;
            }

            var parameter = new OpenApiParameter
            {
                Name     = name,
                In       = location,
                Required = isRequired,
                Schema   = schema
            };

            var filterContext = new ParameterFilterContext(apiParameter, _schemaGenerator, schemaRepository, parameterInfo, propertyInfo);

            foreach (var filter in _options.ParameterFilters)
            {
                filter.Apply(parameter, filterContext);
            }

            return(parameter);
        }
        private OpenApiParameter GenerateParameter(
            ApiParameterDescription apiParameter,
            SchemaRepository schemaRepository)
        {
            var name = _options.DescribeAllParametersInCamelCase
                ? apiParameter.Name.ToCamelCase()
                : apiParameter.Name;

            var location = ParameterLocationMap.ContainsKey(apiParameter.Source)
                ? ParameterLocationMap[apiParameter.Source]
                : ParameterLocation.Query;

            var isRequired = (apiParameter.IsFromPath()) ||
                             apiParameter.CustomAttributes().Any(attr => RequiredAttributeTypes.Contains(attr.GetType()));

            var schema = (apiParameter.ModelMetadata != null)
                ? _schemaGenerator.GenerateSchema(apiParameter.ModelMetadata.ModelType, schemaRepository)
                : new OpenApiSchema {
                Type = "string"
            };

            var defaultValue = apiParameter.CustomAttributes().OfType <DefaultValueAttribute>().FirstOrDefault()?.Value
                               ?? apiParameter.ParameterInfo()?.DefaultValue;

            // NOTE: Oddly, ParameterInfo.DefaultValue returns DBNull if not optional, hence the additional check below
            if (schema.Reference == null && defaultValue != null && defaultValue != DBNull.Value)
            {
                schema.Default = OpenApiAnyFactory.TryCreateFor(schema, defaultValue, out IOpenApiAny openApiAny)
                    ? openApiAny
                    : null;
            }

            var parameter = new OpenApiParameter
            {
                Name     = name,
                In       = location,
                Required = isRequired,
                Schema   = schema
            };

            var filterContext = new ParameterFilterContext(
                apiParameter,
                _schemaGenerator,
                schemaRepository,
                apiParameter.ParameterInfo(),
                apiParameter.PropertyInfo());

            foreach (var filter in _options.ParameterFilters)
            {
                filter.Apply(parameter, filterContext);
            }

            return(parameter);
        }
示例#8
0
        public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!(_contractResolver.ResolveContract(type) is JsonObjectContract jsonObjectContract))
            {
                throw new InvalidOperationException($"Type {type} does not resolve to a JsonObjectContract");
            }

            var schema = new OpenApiSchema
            {
                Type       = "object",
                Properties = new Dictionary <string, OpenApiSchema>(),
                Required   = new SortedSet <string>(),
                Nullable   = (_serializerSettings.NullValueHandling == NullValueHandling.Include)
            };

            foreach (var jsonProperty in jsonObjectContract.Properties)
            {
                if (jsonProperty.Ignored)
                {
                    continue;
                }

                var customAttributes = jsonProperty.TryGetMemberInfo(out MemberInfo memberInfo)
                    ? memberInfo.GetInlineOrMetadataTypeAttributes()
                    : Enumerable.Empty <object>();

                if (_generatorOptions.IgnoreObsoleteProperties && customAttributes.OfType <ObsoleteAttribute>().Any())
                {
                    continue;
                }

                var required = jsonProperty.IsRequiredSpecified()
                    ? jsonProperty.Required
                    : jsonObjectContract.ItemRequired ?? Required.Default;

                schema.Properties.Add(jsonProperty.PropertyName, GeneratePropertySchema(jsonProperty, customAttributes, required, schemaRepository));

                if (required == Required.Always || required == Required.AllowNull || customAttributes.OfType <RequiredAttribute>().Any())
                {
                    schema.Required.Add(jsonProperty.PropertyName);
                }
            }

            if (jsonObjectContract.ExtensionDataValueType != null)
            {
                schema.AdditionalProperties        = _schemaGenerator.GenerateSchema(jsonObjectContract.ExtensionDataValueType, schemaRepository);
                schema.AdditionalPropertiesAllowed = true;
            }

            return(schema);
        }
示例#9
0
        public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
        {
            var schema = new OpenApiSchema
            {
                Type       = "object",
                Properties = new Dictionary <string, OpenApiSchema>(),
                Required   = new SortedSet <string>(),
                Nullable   = true
            };

            var serializableProperties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                         .Where(property =>
            {
                return
                ((property.IsPubliclyReadable() || property.IsPubliclyWritable()) &&
                 !(property.GetIndexParameters().Any()) &&
                 !(property.HasAttribute <JsonIgnoreAttribute>()) &&
                 !(_serializerOptions.IgnoreReadOnlyProperties && !property.IsPubliclyWritable()));
            });

            foreach (var property in serializableProperties)
            {
                var customAttributes = property.GetInlineOrMetadataTypeAttributes();

                if (_generatorOptions.IgnoreObsoleteProperties && customAttributes.OfType <ObsoleteAttribute>().Any())
                {
                    continue;
                }

                var name = property.GetCustomAttribute <JsonPropertyNameAttribute>()?.Name
                           ?? _serializerOptions.PropertyNamingPolicy?.ConvertName(property.Name) ?? property.Name;

                schema.Properties.Add(name, GeneratePropertySchema(property, customAttributes, schemaRepository));

                if (customAttributes.OfType <RequiredAttribute>().Any())
                {
                    schema.Required.Add(name);
                }

                if (property.HasAttribute <JsonExtensionDataAttribute>() && property.PropertyType.IsDictionary(out Type keyType, out Type valueType))
                {
                    schema.AdditionalPropertiesAllowed = true;
                    schema.AdditionalProperties        = _schemaGenerator.GenerateSchema(valueType, schemaRepository);
                }
            }

            return(schema);
        }
示例#10
0
        private static void AddResponseHeaders(
            OpenApiOperation operation,
            ApiResponseType responseType,
            SchemaRepository schemaRepository,
            ISchemaGenerator schemaGenerator)
        {
            var headers = (responseType.ModelMetadata as ApiModelMetadata)?.Headers;

            if (headers == null || headers.Length == 0)
            {
                return;
            }

            if (!operation.Responses.TryGetValue(responseType.StatusCode.ToString(), out var response))
            {
                return;
            }

            for (var i = 0; i < headers.Length; i++)
            {
                var metadata = headers[i];
                var schema   = schemaGenerator.GenerateSchema(metadata.Type, schemaRepository);
                response.Headers.Add(metadata.Name, new OpenApiHeader {
                    Schema = schema
                });
            }
        }
示例#11
0
        public static IEnumerable <EnumMember> ApplyEnumExtensions(this Type type, IDictionary <string, IOpenApiExtension> extensions, ISchemaGenerator schemaGenerator, SchemaRepository schemaRepository)
        {
            type = type.UnwrapIfNullable();

            if (!type.IsEnum || extensions == null)
            {
                return(null);
            }

            var underlyingType = type.GetEnumUnderlyingType();
            var members        = type.GetEnumMembers();

            var memberDictionary = new OpenApiObject();

            foreach (var member in members)
            {
                memberDictionary[member.Name] = new OpenApiLong(long.Parse(member.Value.ToString()));  // Will never be wider than a long.
            }

            var obsoleteDictionary = new OpenApiObject();

            foreach (var field in members.Where(f => f.IsObsolete))
            {
                obsoleteDictionary[field.Name] = new OpenApiString(field.ObsoleteMessage ?? string.Empty);
            }

            var dictionary = new OpenApiObject
            {
                ["id"]     = new OpenApiString(type.FullName),
                ["fields"] = memberDictionary,
            };

            if (obsoleteDictionary.Count > 0)
            {
                dictionary["deprecated"] = obsoleteDictionary;
            }

            if (type.GetCustomAttribute <FlagsAttribute>() != null)
            {
                dictionary["flags"] = new OpenApiBoolean(true);
            }

            var enumSchema = schemaGenerator.GenerateSchema(underlyingType, schemaRepository);

            foreach (var extension in enumSchema.Extensions)
            {
                dictionary[extension.Key] = (IOpenApiAny)extension.Value;
            }

            var obsoleteAttribute = type.GetCustomAttribute <ObsoleteAttribute>();

            if (obsoleteAttribute != null)
            {
                dictionary["x-costar-deprecated"] = new OpenApiString(obsoleteAttribute.Message);
            }

            extensions[VendorExtensions.Enum] = dictionary;

            return(members);
        }
示例#12
0
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            if (context.MethodInfo.DeclaringType != null)
            {
                var attributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
                                 .Union(context.MethodInfo.GetCustomAttributes(true))
                                 .OfType <QueryStringParameterAttribute>();

                foreach (var attribute in attributes)
                {
                    var attributeTypeName = new OpenApiSchema {
                        Type = "string"
                    };

                    operation.Parameters.Add(new OpenApiParameter
                    {
                        Name        = attribute.Name,
                        Description = attribute.Description,
                        In          = ParameterLocation.Query,
                        Required    = attribute.Required,
                        Schema      = schemaGenerator.GenerateSchema(attribute?.DataType, new SchemaRepository())
                    });
                }
            }
        }
示例#13
0
        private OpenApiParameter GenerateParameter(
            ApiParameterDescription apiParameter,
            SchemaRepository schemaRepository)
        {
            var name = _options.DescribeAllParametersInCamelCase
                ? apiParameter.Name.ToCamelCase()
                : apiParameter.Name;

            var location = (apiParameter.Source != null && ParameterLocationMap.ContainsKey(apiParameter.Source))
                ? ParameterLocationMap[apiParameter.Source]
                : ParameterLocation.Query;

            var isRequired = (apiParameter.IsFromPath()) ||
                             apiParameter.CustomAttributes().Any(attr => RequiredAttributeTypes.Contains(attr.GetType()));

            var schema = (apiParameter.ModelMetadata != null)
                ? _schemaGenerator.GenerateSchema(
                apiParameter.ModelMetadata.ModelType,
                schemaRepository,
                apiParameter.PropertyInfo(),
                apiParameter.ParameterInfo())
                : new OpenApiSchema {
                Type = "string"
            };

            var parameter = new OpenApiParameter
            {
                Name     = name,
                In       = location,
                Required = isRequired,
                Schema   = schema
            };

            var filterContext = new ParameterFilterContext(
                apiParameter,
                _schemaGenerator,
                schemaRepository,
                apiParameter.PropertyInfo(),
                apiParameter.ParameterInfo());

            foreach (var filter in _options.ParameterFilters)
            {
                filter.Apply(parameter, filterContext);
            }

            return(parameter);
        }
示例#14
0
        ///<inheritdoc/>
        public override async Task PublishAsync <TIntegrationEvent>(
            TIntegrationEvent @event,
            string topic  = null,
            string prefix = null)
        {
            if (@event is null)
            {
                throw new ArgumentNullException(nameof(@event));
            }
            var topicName = GetTopicName(@event.GetType(), topic, prefix);

            if (_daprEventBusSchemaOptions.Value.UseSchemaRegistry)
            {
                // Get schema
                var schema = await _schemaRegistry.GetSchema(topicName);

                if (schema == null)
                {
                    if (!_daprEventBusSchemaOptions.Value.AddSchemaOnPublish)
                    {
                        _logger.LogError("No schema registered for {TopicName}", topicName);
                        throw new SchemaNotRegisteredException(topicName);
                    }

                    // Generate schema
                    var content = _schemaGenerator.GenerateSchema(typeof(TIntegrationEvent));
                    if (string.IsNullOrWhiteSpace(content))
                    {
                        _logger.LogError("Schema generation failed for {TopicName}", topicName);
                        throw new Exception($"Schema generation failed for {topicName}");
                    }

                    // Register schema
                    schema = new Schema
                    {
                        Topic   = topicName,
                        Content = content
                    };
                    await _schemaRegistry.AddSchema(schema);

                    _logger.LogInformation("Schema registered for {TopicName}", topicName);
                }

                // Validate message with schema
                var message = JsonSerializer.Serialize(@event, typeof(TIntegrationEvent), DaprClient.JsonSerializerOptions);
                var isValid = _schemaValidator.ValidateMessage(message, schema.Content, out var errorMessages);
                if (!isValid)
                {
                    _logger.LogError("Schema validation failed for {TopicName}", topicName);
                    foreach (var errorMessage in errorMessages)
                    {
                        _logger.LogError("Schema validation error: {ErrorMessage}", errorMessage);
                    }
                    throw new SchemaValidationException(topicName);
                }
            }

            await DaprClient.PublishEventAsync(DaprEventBusOptions.Value.PubSubName, topicName, @event);
        }
示例#15
0
        private Message GenerateMessageFromAttribute(MessageAttribute messageAttribute, ISchemaRepository schemaRepository)
        {
            if (messageAttribute?.PayloadType == null)
            {
                return(null);
            }

            var message = new Message
            {
                Payload     = _schemaGenerator.GenerateSchema(messageAttribute.PayloadType, schemaRepository),
                Name        = messageAttribute.Name ?? _options.SchemaIdSelector(messageAttribute.PayloadType),
                Title       = messageAttribute.Title,
                Summary     = messageAttribute.Summary,
                Description = messageAttribute.Description,
            };

            return(message);
        }
示例#16
0
 IDictionary <string, OpenApiMediaType> GenerateContentType(string mimeType, Type type, SchemaRepository repository)
 {
     return(new Dictionary <string, OpenApiMediaType>
     {
         [mimeType] = new OpenApiMediaType {
             Schema = _schemaGenerator.GenerateSchema(type, repository)
         }
     });
 }
示例#17
0
 public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
 {
     return(new OpenApiSchema
     {
         OneOf = _generatorOptions.SubTypesResolver(type)
                 .Select(subType => _schemaGenerator.GenerateSchema(subType, schemaRepository))
                 .ToList()
     });
 }
示例#18
0
        private OpenApiSchema GenerateSchema(Type type)
        {
            if (type == typeof(Task))
            {
                return(null);
            }

            return(_schemaGenerator.GenerateSchema(type, _schemaRepository));
        }
示例#19
0
        private Response CreateResponseSchema(
            IEnumerable <RouteDocs> routes,
            SwaggerAggregateRoute aggregateRoute,
            OpenApiDocument openApiDocument)
        {
            AggregateResponseAttribute attribute = GetAggregatorAttribute(aggregateRoute);

            if (attribute != null)
            {
                OpenApiSchema reference = _schemaGenerator.GenerateSchema(attribute.ResponseType, _schemaRepository);
                var           response  = new Response()
                {
                    Description = attribute.Description,
                    MediaType   = attribute.MediaType,
                    StatusCode  = attribute.StatusCode
                };
                foreach (KeyValuePair <string, OpenApiSchema> item in _schemaRepository.Schemas)
                {
                    openApiDocument.Components.Schemas.Add(item.Key, item.Value);
                }

                if (reference.Reference != null)
                {
                    response.Schema = _schemaRepository.Schemas[reference.Reference.Id];
                }
                else
                {
                    response.Schema = reference;
                }

                return(response);
            }

            var schema = new OpenApiSchema
            {
                Type       = "object",
                Properties = new Dictionary <string, OpenApiSchema>(),
                Required   = new SortedSet <string>(),
                AdditionalPropertiesAllowed = false
            };

            foreach (RouteDocs docs in routes)
            {
                OpenApiResponse response = docs.GetResponse();
                if (response.Content.ContainsKey(MediaTypeNames.Application.Json))
                {
                    OpenApiMediaType content = response.Content[MediaTypeNames.Application.Json];
                    schema.Properties.Add(docs.Key, content.Schema);
                }
            }

            return(new Response()
            {
                Schema = schema
            });
        }
 OpenApiParameter GenerateEventSourceIdParameter(ISchemaGenerator schemaGenerator, SchemaRepository repository)
 {
     return(new OpenApiParameter
     {
         Name = "EventSource-ID",
         In = ParameterLocation.Query,
         Required = true,
         Schema = schemaGenerator.GenerateSchema(typeof(EventSourceId), repository),
     });
 }
 public void AddAdditionalSchemas(ISchemaGenerator schemaGenerator, SchemaRepository schemaRepository)
 {
     foreach (var model in _listModels
              .Where(x => !schemaRepository.Schemas
                     .Select(schema => schema.Key.ToLower())
                     .Contains(x.Name.ToLower())))
     {
         schemaGenerator.GenerateSchema(model, schemaRepository);
     }
 }
        private Message GenerateMessage(MethodInfo method, OperationAttribute operationAttribute, ISchemaRepository schemaRepository)
        {
            var message = new Message
            {
                Payload = _schemaGenerator.GenerateSchema(operationAttribute.MessagePayloadType, schemaRepository),
                // todo: all the other properties... message has a lot!
            };

            return(message);
        }
示例#23
0
 OpenApiParameter GenerateTenantIdParameter(ISchemaGenerator schemaGenerator, SchemaRepository repository)
 {
     return(new OpenApiParameter
     {
         Name = "Tenant-ID",
         In = ParameterLocation.Header,
         Required = true,
         Schema = schemaGenerator.GenerateSchema(typeof(TenantId), repository),
     });
 }
示例#24
0
        private void AddPathParams(ContractMethod contractMethod, OpenApiOperation operation, HttpRoutInfo routInfo)
        {
            ValidatePath(contractMethod, routInfo);

            foreach (var p in contractMethod.InnerSystemTypeParameters)
            {
                if (routInfo.IsPath(p.Name))
                {
                    var schema = _schemaGenerator.GenerateSchema(p.Type, SchemaRepository, p.PropertyInfo !, p.ParameterInfo !);
                    operation.Parameters.Add(new OpenApiParameter
                    {
                        In          = ParameterLocation.Path,
                        Name        = p.Name,
                        Schema      = schema,
                        Description = schema.Description,
                        Required    = true
                    });
                }
            }
        }
示例#25
0
        public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!(_contractResolver.ResolveContract(type) is JsonDictionaryContract jsonDictionaryContract))
            {
                throw new InvalidOperationException($"Type {type} does not resolve to a JsonDictionaryContract");
            }

            var keyType   = jsonDictionaryContract.DictionaryKeyType ?? typeof(object);
            var valueType = jsonDictionaryContract.DictionaryValueType ?? typeof(object);

            OpenApiSchema schema;

            if (keyType.IsEnum)
            {
                // This is a special case where we can include named properties based on the enum values
                schema = new OpenApiSchema
                {
                    Type       = "object",
                    Properties = keyType.GetEnumNames()
                                 .ToDictionary(
                        name => name,
                        name => _schemaGenerator.GenerateSchema(valueType, schemaRepository)
                        )
                };
            }
            else
            {
                schema = new OpenApiSchema
                {
                    Type = "object",
                    AdditionalPropertiesAllowed = true,
                    AdditionalProperties        = _schemaGenerator.GenerateSchema(valueType, schemaRepository)
                };
            }

            schema.Nullable = (_serializerSettings.NullValueHandling == NullValueHandling.Include);

            return(schema);
        }
示例#26
0
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.Tags ??= new List <OpenApiTag>();

        var tag = new OpenApiTag
        {
            Name        = "Workflow Endpoints",
            Description = "A collection of HTTP endpoints exposed by workflows",
        };

        var schemaRepository = context.SchemaRepository;

        swaggerDoc.Tags.Add(tag);

        var httpEndpoints = FindHttpEndpointsAsync(CancellationToken.None).ToLookupAsync(x => x.Path).Result;

        foreach (var grouping in httpEndpoints)
        {
            var path  = grouping.Key;
            var first = grouping.First();

            swaggerDoc.Paths.Add(path, new OpenApiPathItem
            {
                Description = first.Description,
                Operations  = grouping.ToDictionary(GetOperationType, httpEndpoint =>
                {
                    var operation = new OpenApiOperation
                    {
                        Tags = { tag },
                    };

                    if (httpEndpoint.TargetType != null || httpEndpoint.JsonSchema != null)
                    {
                        operation.RequestBody = new OpenApiRequestBody
                        {
                            Required = true,
                            Content  =
                            {
                                ["Unspecified"] = new OpenApiMediaType
                                {
                                Schema = httpEndpoint.TargetType != null ? _schemaGenerator.GenerateSchema(httpEndpoint.TargetType, schemaRepository) : new OpenApiSchema()     // TODO: Convert JSON schema into OpenAPI schema.
                                }
                            }
                        };
                    }

                    return(operation);
                })
            });
        }
    }
示例#27
0
        /// <inheritdoc />
        public void Apply([NotNull] OpenApiOperation operation, [NotNull] OperationFilterContext context)
        {
            if (operation.Deprecated ||
                !Enum.TryParse(context.ApiDescription.HttpMethod, true, out HttpMethod method) ||
                !method.In(HttpMethod.Post, HttpMethod.Put))
            {
                return;
            }

            // Check if any of the parameters' types or their nested properties / fields are supported
            if (!Enumerate(context.ApiDescription.ActionDescriptor).Any(e => IsSupported(e.ParameterType)))
            {
                return;
            }

            OpenApiMediaType uploadFileMediaType = operation.RequestBody.Content.GetOrAdd(MediaTypeNames.Multipart.FormData, _ => new OpenApiMediaType
            {
                Schema = new OpenApiSchema
                {
                    Type       = "object",
                    Properties = new Dictionary <string, OpenApiSchema>(StringComparer.OrdinalIgnoreCase),
                    Required   = new HashSet <string>(StringComparer.OrdinalIgnoreCase)
                }
            });

            IDictionary <string, OpenApiSchema> schemaProperties = uploadFileMediaType.Schema.Properties;
            ISet <string>    schemaRequired = uploadFileMediaType.Schema.Required;
            ISchemaGenerator generator      = context.SchemaGenerator;
            SchemaRepository repository     = context.SchemaRepository;

            foreach (ParameterDescriptor parameter in Enumerate(context.ApiDescription.ActionDescriptor))
            {
                OpenApiSchema schema = generator.GenerateSchema(parameter.ParameterType, repository);
                if (schema == null)
                {
                    continue;
                }

                if (IsSupported(parameter.ParameterType))
                {
                    schema.Type = "file";
                }
                schemaProperties.Add(parameter.Name, schema);

                if (parameter.ParameterType.IsPrimitive && !parameter.ParameterType.IsNullable() ||
                    !parameter.ParameterType.IsInterface && !parameter.ParameterType.IsClass || parameter.ParameterType.HasAttribute <RequiredAttribute>())
                {
                    schemaRequired.Add(parameter.Name);
                }
            }
示例#28
0
        public override OpenApiSchema CreateSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!type.IsEnumerable(out Type itemType))
            {
                throw new InvalidOperationException($"Type {type} is not enumerable");
            }

            return(new OpenApiSchema
            {
                Type = "array",
                Items = _schemaGenerator.GenerateSchema(itemType, schemaRepository),
                UniqueItems = type.IsSet() ? (bool?)true : null
            });
        }
示例#29
0
        public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!type.IsDictionary(out Type keyType, out Type valueType))
            {
                throw new InvalidOperationException($"Type {type} is not a dictionary");
            }

            OpenApiSchema schema;

            if (keyType.IsEnum)
            {
                // This is a special case where we can include named properties based on the enum values
                schema = new OpenApiSchema
                {
                    Type       = "object",
                    Properties = keyType.GetEnumNames()
                                 .ToDictionary(
                        name => name,
                        name => _schemaGenerator.GenerateSchema(valueType, schemaRepository)
                        )
                };
            }
            else
            {
                schema = new OpenApiSchema
                {
                    Type = "object",
                    AdditionalPropertiesAllowed = true,
                    AdditionalProperties        = _schemaGenerator.GenerateSchema(valueType, schemaRepository)
                };
            }

            schema.Nullable = !_serializerOptions.IgnoreNullValues;

            return(schema);
        }
        public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
        {
            if (!(_contractResolver.ResolveContract(type) is JsonArrayContract jsonArrayContract))
            {
                throw new InvalidOperationException($"Type {type} does not resolve to a JsonArrayContract");
            }

            var itemType = jsonArrayContract.CollectionItemType ?? typeof(object);

            return(new OpenApiSchema
            {
                Type = "array",
                Items = _schemaGenerator.GenerateSchema(itemType, schemaRepository),
                UniqueItems = type.IsSet() ? (bool?)true : null
            });
        }