public void Apply(OpenApiOperation operation, OperationFilterContext context) { var attribute = context.MethodInfo.DeclaringType.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) .OfType <FormContentAttribute>().FirstOrDefault(); if (attribute == null) { return; } var uploadFileMediaType = new OpenApiMediaType { Schema = new OpenApiSchema() { Type = "object", Properties = ConfigurFormProperties(attribute.elements), Required = ConfigureRequiredProperties(attribute.elements) } }; operation.RequestBody = new OpenApiRequestBody { Content = { ["application/x-www-form-urlencoded"] = uploadFileMediaType } }; }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { //https://stackoverflow.com/questions/39152612/swashbuckle-5-and-multipart-form-data-helppages var uploadFileMediaType = new OpenApiMediaType() { Schema = new OpenApiSchema() { Type = "object", Properties = { ["file"] = new OpenApiSchema() { Type = "file" } } } }; operation.RequestBody = new OpenApiRequestBody { Content = { ["multipart/form-data"] = uploadFileMediaType } }; }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { if (operation.OperationId == "Import") { operation.Parameters.Clear(); var uploadFileMediaType = new OpenApiMediaType() { Schema = new OpenApiSchema() { Type = "object", // the type of thing to send Properties = { ["campaignFile"] = new OpenApiSchema() { Description = "Upload File", Type = "file", Format = "binary", } }, Required = new HashSet <string>() { "campaignFile" } } }; operation.RequestBody = new OpenApiRequestBody { Content = { ["multipart/form-data"] = uploadFileMediaType } }; } }
public void CreateResponseForEdmFunctionOfStreamReturnTypeReturnsCorrectResponse() { // Arrange string operationName = "getMailboxUsageStorage"; IEdmModel model = EdmModelHelper.GraphBetaModel; ODataContext context = new(model); // Act OpenApiResponses responses; IEdmOperation operation = model.SchemaElements.OfType <IEdmOperation>().First(o => o.Name == operationName); Assert.NotNull(operation); // guard ODataPath path = new(new ODataOperationSegment(operation)); responses = context.CreateResponses(operation, path); // Assert Assert.NotNull(responses); Assert.NotEmpty(responses); Assert.Equal(2, responses.Count); Assert.Equal(new string[] { "200", "default" }, responses.Select(r => r.Key)); OpenApiResponse response = responses["200"]; Assert.NotNull(response.Content); OpenApiMediaType mediaType = response.Content["application/octet-stream"]; }
private static OpenApiRequestBody CreateFormBody(ParsingContext context, List <OpenApiParameter> formParameters) { var mediaType = new OpenApiMediaType { Schema = new OpenApiSchema { Properties = formParameters.ToDictionary( k => k.Name, v => { var schema = v.Schema; schema.Description = v.Description; schema.Extensions = v.Extensions; return(schema); }), Required = new HashSet <string>(formParameters.Where(p => p.Required).Select(p => p.Name)) } }; var consumes = context.GetFromTempStorage <List <string> >(TempStorageKeys.OperationConsumes) ?? context.GetFromTempStorage <List <string> >(TempStorageKeys.GlobalConsumes) ?? new List <string> { "application/x-www-form-urlencoded" }; var formBody = new OpenApiRequestBody { Content = consumes.ToDictionary( k => k, v => mediaType) }; return(formBody); }
/// <summary> /// Foreach http status code keep the media type for application/json /// and remove the other media types. /// </summary> /// <param name="operation">API Operation</param> /// <param name="context">Filter context</param> public void Apply(OpenApiOperation operation, OperationFilterContext context) { // If there already is a consume attribute, this won't be overridden, // so only if nothing is configured, the default will be set to application/json. bool hasConsumeAttribute = context.MethodInfo.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) .OfType <ConsumesAttribute>() .Count() != 0; if (operation.RequestBody != null && !hasConsumeAttribute) { OpenApiMediaType mediaType = operation.RequestBody.Content["application/json"]; operation.RequestBody.Content.Clear(); operation.RequestBody.Content.Add("application/json", mediaType); } foreach (string code in operation.Responses.Keys) { if (operation.Responses[code] .Content.TryGetValue("application/json", out OpenApiMediaType mediaType)) { operation.Responses[code] .Content.Clear(); operation.Responses[code] .Content.Add("application/json", mediaType); } } }
private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, ParsingContext context) { var produces = context.GetFromTempStorage <List <string> >(TempStorageKeys.OperationProduces) ?? context.GetFromTempStorage <List <string> >(TempStorageKeys.GlobalProduces) ?? new List <string>(); if (response.Content == null) { response.Content = new Dictionary <string, OpenApiMediaType>(); } foreach (var produce in produces) { var schema = context.GetFromTempStorage <OpenApiSchema>(TempStorageKeys.ResponseSchema, response); context.SetTempStorage(TempStorageKeys.ResponseSchema, null, response); if (response.Content.ContainsKey(produce) && response.Content[produce] != null) { if (schema != null) { response.Content[produce].Schema = schema; ProcessAnyFields(mapNode, response.Content[produce], _mediaTypeAnyFields); } } else { var mediaType = new OpenApiMediaType { Schema = schema }; response.Content.Add(produce, mediaType); } } }
public OpenApiMediaType GenerateMemberType( Collection collection, List <Attribute> collection_attributes, bool excludeKeyAttributes = false, bool excludeKeyAutoAttributes = false) { var type = new OpenApiMediaType(); type.Schema = new OpenApiSchema(); type.Schema.Type = "object"; type.Schema.Title = collection.membername; type.Schema.Xml = new OpenApiXml() { Name = collection.membername, }; foreach (var attribute in collection_attributes) { if (attribute.keyindex.HasValue && excludeKeyAttributes) { continue; } if (attribute.keyindex.HasValue && attribute.autovalue && excludeKeyAutoAttributes) { continue; } type.Schema.Properties.Add(attribute.attributename, new OpenApiSchema() { Title = attribute.attributename, Type = attribute.type, Format = attribute.format, Nullable = attribute.nullable }); } return(type); }
public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() { // Arrange IEnumerable <OpenApiError> errors; var mediaType = new OpenApiMediaType() { Example = new OpenApiInteger(55), Schema = new OpenApiSchema() { Type = "string", } }; // Act var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); var walker = new OpenApiWalker(validator); walker.Walk(mediaType); errors = validator.Errors; bool result = !errors.Any(); // Assert result.Should().BeFalse(); errors.Select(e => e.Message).Should().BeEquivalentTo(new[] { RuleHelpers.DataTypeMismatchedErrorMessage }); errors.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { "#/example", }); }
/// <summary> /// Constructs an OpenApi document that will mapper the /swagger endpoint to the operation. /// </summary> /// <returns> /// The <see cref="OpenApiDocument"/>. /// </returns> public static OpenApiDocument BuildSwaggerDocument() { var jsonMediaType = new OpenApiMediaType { Schema = new OpenApiSchema { Type = "object" } }; var response = new OpenApiResponse(); response.Content.Add("application/json", jsonMediaType); response.Description = "OK"; var operation = new OpenApiOperation { OperationId = SwaggerOperationId, Summary = "View swagger definition for this API", Description = "View swagger definition for this API", }; operation.Responses.Add("200", response); var pathItem = new OpenApiPathItem(); pathItem.Operations.Add(OperationType.Get, operation); return(new OpenApiDocument { Paths = new OpenApiPaths { { "/swagger", pathItem }, }, }); }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { if (operation.OperationId == "Post_JsonFile") { operation.Parameters.Clear(); var uploadFileMediaType = new OpenApiMediaType() { Schema = new OpenApiSchema() { Type = "object", Properties = { ["uploadedJsonFile"] = new OpenApiSchema() { Description = "Upload JSON File", Type = "file", Format = "binary" } }, Required = new HashSet <string>() { "uploadedJsonFile" } } }; operation.RequestBody = new OpenApiRequestBody { Content = { ["multipart/form-data"] = uploadFileMediaType } }; } }
private static void LoadExample(OpenApiResponse response, string mediaType, ParseNode node) { var exampleNode = node.CreateAny(); if (response.Content == null) { response.Content = new Dictionary <string, OpenApiMediaType>(); } OpenApiMediaType mediaTypeObject; if (response.Content.ContainsKey(mediaType)) { mediaTypeObject = response.Content[mediaType]; } else { mediaTypeObject = new OpenApiMediaType { Schema = node.Context.GetFromTempStorage <OpenApiSchema>(TempStorageKeys.ResponseSchema, response) }; response.Content.Add(mediaType, mediaTypeObject); } mediaTypeObject.Example = exampleNode; }
private static void SetMultipartFormDataForUploadFile(OpenApiDocument document) { foreach (var operation in document.Operations) { var fileParameters = operation.Operation.Parameters.Where(p => p.Type == NJsonSchema.JsonObjectType.File).ToList(); if (fileParameters.Any()) { operation.Operation.RequestBody = new OpenApiRequestBody(); var requestBodyContent = new OpenApiMediaType { Schema = new NJsonSchema.JsonSchema() }; requestBodyContent.Schema.Type = NJsonSchema.JsonObjectType.Object; foreach (var fileParameter in fileParameters) { requestBodyContent.Schema.Properties.Add(fileParameter.Name, new NJsonSchema.JsonSchemaProperty { Type = NJsonSchema.JsonObjectType.String, Format = "binary", Description = fileParameter.Description }); operation.Operation.Parameters.Remove(fileParameter); } operation.Operation.RequestBody.Content.Add("multipart/form-data", requestBodyContent); } } }
private void AddType <T>(string mediaTypeName, string description, OpenApiOperation operation, OperationFilterContext context) { if (context.SchemaRepository.Schemas.TryGetValue(nameof(T), out var schema)) { return; } schema = context.SchemaGenerator.GenerateSchema(typeof(T), context.SchemaRepository); schema.Description = description; var value = new OpenApiMediaType() { Schema = schema }; if (operation.Responses[StatusCodes.Status200OK.ToString()].Content.ContainsKey(mediaTypeName)) { var u = operation.Responses[StatusCodes.Status200OK.ToString()].Content[mediaTypeName]; u.Schema = schema; } else { operation.Responses[StatusCodes.Status200OK.ToString()].Content.Add(mediaTypeName, value); } }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { EnsureArg.IsNotNull(operation, nameof(operation)); EnsureArg.IsNotNull(context, nameof(context)); foreach (ApiResponseType responseType in context.ApiDescription.SupportedResponseTypes) { if (responseType.StatusCode == 400 || responseType.StatusCode == 404 || responseType.StatusCode == 406 || responseType.StatusCode == 415) { string responseKey = responseType.IsDefaultResponse ? "default" : responseType.StatusCode.ToString(); OpenApiResponse response = operation.Responses[responseKey]; foreach (string contentType in response.Content.Keys) { if (response.Content.Count == 1) { OpenApiMediaType value = response.Content[contentType]; response.Content.Remove(contentType); response.Content.Add("application/json", value); break; } response.Content.Remove(contentType); } operation.Responses[responseKey] = response; } } }
public static OpenApiResponse CreateContent(this OpenApiResponse parent, string mediaType, Action <OpenApiMediaType> config) { var child = new OpenApiMediaType(); config(child); parent.Content.Add(mediaType, child); return(parent); }
public void CreateResponseForEdmFunctionReturnCorrectResponses(bool isFunctionImport, OpenApiSpecVersion specVersion) { // Arrange string operationName = "GetPersonWithMostFriends"; IEdmModel model = EdmModelHelper.TripServiceModel; ODataContext context = new ODataContext(model); context.Settings.OpenApiSpecVersion = specVersion; // Act OpenApiResponses responses; if (isFunctionImport) { IEdmOperationImport operationImport = model.EntityContainer.OperationImports().First(o => o.Name == operationName); Assert.NotNull(operationImport); // guard responses = context.CreateResponses(operationImport); } else { IEdmOperation operation = model.SchemaElements.OfType <IEdmOperation>().First(o => o.Name == operationName); Assert.NotNull(operation); // guard responses = context.CreateResponses(operation); } // Assert Assert.NotNull(responses); Assert.NotEmpty(responses); Assert.Equal(2, responses.Count); Assert.Equal(new string[] { "200", "default" }, responses.Select(r => r.Key)); OpenApiResponse response = responses["200"]; Assert.NotNull(response.Content); OpenApiMediaType mediaType = response.Content["application/json"]; // For either version, nullable should be set // and the serializer will ignore for v2 Assert.True(mediaType.Schema.Nullable); // openApi version 2 should have not use nullable if (specVersion == OpenApiSpecVersion.OpenApi2_0) { Assert.NotNull(mediaType.Schema); Assert.Null(mediaType.Schema.AnyOf); Assert.NotNull(mediaType.Schema.Reference); Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", mediaType.Schema.Reference.Id); } else { Assert.NotNull(mediaType.Schema); Assert.Null(mediaType.Schema.Reference); Assert.NotNull(mediaType.Schema.AnyOf); var anyOf = Assert.Single(mediaType.Schema.AnyOf); Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", anyOf.Reference.Id); } }
public Task <bool> ProcessAsync(OperationProcessorContext context) { SwaggerOperation operation = context.OperationDescription.Operation; OpenApiMediaType mediaType = operation.RequestBody.Content.First().Value; mediaType.Example = _requestObj; return(Task.FromResult(true)); }
private static OpenApiMediaType GeneratePatchOperationsType( Collection collection) { #region operation var type = new OpenApiMediaType(); type.Schema = new OpenApiSchema(); type.Schema.Type = "object"; type.Schema.Title = "operation"; type.Schema.Xml = new OpenApiXml() { Name = "operation", Wrapped = true }; type.Schema.Description = "operation is a json-patch operation, compliant to RFC6902 (https://datatracker.ietf.org/doc/html/rfc6902)"; type.Schema.Properties.Add("op", new OpenApiSchema() { Title = "op", Type = "string", Format = null, Nullable = false }); type.Schema.Properties.Add("path", new OpenApiSchema() { Title = "path", Type = "string", Format = null, Nullable = false }); type.Schema.Properties.Add("value", new OpenApiSchema() { Title = "op", Type = "string", Format = null, Nullable = true }); #endregion #region operations var arrtype = new OpenApiMediaType(); arrtype.Schema = new OpenApiSchema() { Items = type.Schema, Type = "array", Title = "operations", }; arrtype.Schema.Items.Xml = type.Schema.Xml; arrtype.Schema.Xml = new OpenApiXml() { Name = "operations", Wrapped = true, }; #endregion return(arrtype); }
/// <summary> /// Visits <see cref="OpenApiMediaType"/> and child objects /// </summary> /// <param name="mediaType"></param> internal void Walk(OpenApiMediaType mediaType) { _visitor.Visit(mediaType); Walk(mediaType.Examples); Walk(mediaType.Schema); Walk(mediaType.Encoding); Walk(mediaType as IOpenApiExtensible); }
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 }); }
public override void Visit(OpenApiMediaType mediaType) { var schema = ResolveElement(mediaType.Schema); if (schema != null) { mediaType.Schema = schema as OpenApiSchema; } ResolveDict(mediaType.Examples); }
private static void AddEncoding(OpenApiMediaType mediaType, PropertyInfo propertyInfo) { mediaType.Encoding = mediaType.Encoding .Where(pair => !pair.Key.ToLower().Contains(propertyInfo.Name.ToLower())) .ToDictionary(pair => pair.Key, pair => pair.Value); mediaType.Encoding.Add(propertyInfo.Name, new OpenApiEncoding() { ContentType = "application/json", Explode = false }); }
public static OpenApiMediaType GetOpenApiMediaType(Type type) { OpenApiMediaType mediaType = new OpenApiMediaType(); mediaType.Schema = new OpenApiSchema(); mediaType.Schema.Items = new OpenApiSchema(); mediaType.Schema.Items.Reference = new OpenApiReference(); mediaType.Schema.Items.Reference.Type = ReferenceType.Schema; mediaType.Schema.Items.Reference.Id = type.GetName(); return(mediaType); }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { var fileParams = context.MethodInfo.GetParameters().Where(p => p.ParameterType.FullName?.Equals(typeof(Microsoft.AspNetCore.Http.IFormFile).FullName) == true); if (fileParams.Any() && fileParams.Count() == 1) { var title = "The file to be uploaded"; var description = "The file to be uploaded"; int? maxLength = 5_242_880; bool required = true; var descriptionAttribute = fileParams.First().CustomAttributes.FirstOrDefault(a => a.AttributeType == typeof(FormFileDescriptorAttribute)); if (descriptionAttribute?.ConstructorArguments.Count > 3) { title = descriptionAttribute.ConstructorArguments[0].Value.ToString(); description = descriptionAttribute.ConstructorArguments[1].Value.ToString(); required = (bool)descriptionAttribute.ConstructorArguments[2].Value; maxLength = (int)descriptionAttribute.ConstructorArguments[3].Value; } var uploadFileMediaType = new OpenApiMediaType() { Schema = new OpenApiSchema() { Type = "object", Properties = { [fileParams.First().Name] = new OpenApiSchema() { Description = description, Type = "file", Format = "binary", Title = title, MaxLength = maxLength } } } }; if (required) { uploadFileMediaType.Schema.Required = new HashSet <string>() { fileParams.First().Name }; } operation.RequestBody = new OpenApiRequestBody { Content = { ["multipart/form-data"] = uploadFileMediaType } }; } }
private void GenerateSuccessResponse(IEndPointMethodHandler endPointMethodHandler, OpenApiResponses responses) { var successStatusCode = endPointMethodHandler.Configuration.SuccessStatusCode.ToString(); var contentDictionary = new Dictionary <string, OpenApiMediaType>(); var response = new OpenApiResponse { Content = contentDictionary, Description = "Success" }; OpenApiSchema responseSchema = null; var returnType = endPointMethodHandler.Configuration.DocumentationReturnType; if (returnType.IsConstructedGenericType && (returnType.GetGenericTypeDefinition() == typeof(Task <>) || returnType.GetGenericTypeDefinition() == typeof(ValueTask <>))) { returnType = returnType.GenericTypeArguments[0]; } if (endPointMethodHandler.Configuration.WrappedType != null) { responseSchema = new OpenApiSchema { Properties = new Dictionary <string, OpenApiSchema> { { "result", _apiSchemaGenerator.GetSchemaType(returnType) } } }; } else { responseSchema = _apiSchemaGenerator.GetSchemaType(returnType); } if (string.IsNullOrEmpty(endPointMethodHandler.Configuration.RawContentType)) { foreach (var supportedContentType in _contentSerializationService.SupportedContentTypes) { contentDictionary[supportedContentType] = new OpenApiMediaType { Schema = responseSchema }; } } else { contentDictionary[endPointMethodHandler.Configuration.RawContentType] = new OpenApiMediaType { Schema = responseSchema }; } responses.Add(successStatusCode, response); }
public static OpenApiMediaType LoadMediaType(ParseNode node) { var mapNode = node.CheckMapNode(OpenApiConstants.Content); var mediaType = new OpenApiMediaType(); ParseMap(mapNode, mediaType, _mediaTypeFixedFields, _mediaTypePatternFields); ProcessAnyFields(mapNode, mediaType, _mediaTypeAnyFields); ProcessAnyMapFields(mapNode, mediaType, _mediaTypeAnyMapOpenApiExampleFields); return(mediaType); }
/// <summary> /// Visits <see cref="OpenApiMediaType"/> and child objects /// </summary> internal void Walk(OpenApiMediaType mediaType) { if (mediaType == null) { return; } _visitor.Visit(mediaType); Walk(OpenApiConstants.Example, () => Walk(mediaType.Examples)); Walk(OpenApiConstants.Schema, () => Walk(mediaType.Schema)); Walk(OpenApiConstants.Encoding, () => Walk(mediaType.Encoding)); Walk(mediaType as IOpenApiExtensible); }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { var apiKeyParameter = new OpenApiParameter { Name = "X-API-KEY", In = ParameterLocation.Header, Schema = new OpenApiSchema { Type = "string" }, Required = true, }; if (context.ApiDescription.RelativePath == "pdf/fromHtmlString") { operation.Parameters.Insert(0, apiKeyParameter); } if (context.ApiDescription.RelativePath == "pdf/fromImage") { operation.Parameters.Insert(0, apiKeyParameter); var mediaType = new OpenApiMediaType() { Schema = new OpenApiSchema() { Type = "object", Properties = { ["image"] = new OpenApiSchema { Type = "file", Format = "binary" }, ["title"] = new OpenApiSchema { Type = "string" } }, Required = new HashSet <string>() { "image" } } }; operation.RequestBody = new OpenApiRequestBody { Content = { ["multipart/form-data"] = mediaType } }; } }
/// <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); } }