Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Adds ability to change the response or request body content media type based on custom annotation properties #500

Merged
merged 15 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<PackageId>Microsoft.OpenApi.OData</PackageId>
<SignAssembly>true</SignAssembly>
<Version>1.6.0-preview.9</Version>
<Version>1.6.0-preview.10</Version>
<Description>This package contains the codes you need to convert OData CSDL to Open API Document of Model.</Description>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageTags>Microsoft OpenApi OData EDM</PackageTags>
Expand All @@ -31,6 +31,7 @@
- Use alternate keys in the generation of operation ids of operations and navigation property alternate paths #488
- Fixes operation ids of paths with type cast segments #492
- Uses convert setting to toggle between generating query options schemas of type string array or enums #197
- Adds ability to change the response or request body content media type based on custom annotation properties #405
</PackageReleaseNotes>
<AssemblyName>Microsoft.OpenApi.OData.Reader</AssemblyName>
<AssemblyOriginatorKeyFile>..\..\tool\Microsoft.OpenApi.OData.snk</AssemblyOriginatorKeyFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private IDictionary<string, OpenApiMediaType> GetContentDescription()
}
else
{
// Default content type
// Default stream content type
content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType
{
Schema = new OpenApiSchema
Expand All @@ -147,11 +147,29 @@ private IDictionary<string, OpenApiMediaType> GetContentDescription()
});
}
}

content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
});
else
{
// Add the annotated request content media types
IEnumerable<string> mediaTypes = _insertRestrictions?.RequestContentTypes;
if (mediaTypes != null)
{
foreach (string mediaType in mediaTypes)
{
content.Add(mediaType, new OpenApiMediaType
{
Schema = schema
});
}
}
else
{
// Default content type
content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
});
}
}

return content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,41 @@ protected override void SetRequestBody(OpenApiOperation operation)
{
Required = true,
Description = "New property values",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = GetOpenApiSchema()
}
}
}
Content = GetContent()
};

base.SetRequestBody(operation);
}

protected IDictionary<string, OpenApiMediaType> GetContent()
{
OpenApiSchema schema = GetOpenApiSchema();
var content = new Dictionary<string, OpenApiMediaType>();
IEnumerable<string> mediaTypes = _updateRestrictions?.RequestContentTypes;

// Add the annotated request content media types
if (mediaTypes != null)
{
foreach (string mediaType in mediaTypes)
{
content.Add(mediaType, new OpenApiMediaType
{
Schema = schema
});
}
}
else
{
// Default content type
content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
});
};

return content;
}

/// <inheritdoc/>
protected override void SetResponses(OpenApiOperation operation)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------

using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
Expand Down Expand Up @@ -137,5 +138,45 @@ protected IRecord GetRestrictionAnnotation(string annotationTerm)
_ => null,
};
}

protected IDictionary<string, OpenApiMediaType> GetContent(OpenApiSchema schema = null, IEnumerable<string> mediaTypes = null)
{
schema ??= GetOpenApiSchema();
var content = new Dictionary<string, OpenApiMediaType>();

if (mediaTypes != null)
{
foreach (string mediaType in mediaTypes)
{
content.Add(mediaType, new OpenApiMediaType
{
Schema = schema
});
}
}
else
{
// Default content type
content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
});
};

return content;
}

protected OpenApiSchema GetOpenApiSchema()
{
return new OpenApiSchema
{
UnresolvedReference = true,
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = NavigationProperty.ToEntityType().FullName()
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------

using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
Expand Down Expand Up @@ -53,93 +52,50 @@ protected override void SetBasicInfo(OpenApiOperation operation)

/// <inheritdoc/>
protected override void SetRequestBody(OpenApiOperation operation)
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
UnresolvedReference = true,
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = NavigationProperty.ToEntityType().FullName()
}
};
}

{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
}

operation.RequestBody = new OpenApiRequestBody
{
Required = true,
Description = "New navigation property",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
}
}
}
Content = GetContent(schema, _insertRestriction?.RequestContentTypes)
};

base.SetRequestBody(operation);
}

/// <inheritdoc/>
protected override void SetResponses(OpenApiOperation operation)
{
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
UnresolvedReference = true,
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = NavigationProperty.ToEntityType().FullName()
}
};
}

operation.Responses = new OpenApiResponses
{
{
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode201,
new OpenApiResponse
{
Description = "Created navigation property.",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationJsonMediaType,
new OpenApiMediaType
{
Schema = schema
}
}
}
Content = GetContent(schema, _insertRestriction?.ResponseContentTypes)
}
}
};
operation.AddErrorResponses(Context.Settings, false);

base.SetResponses(operation);
}

}
protected override void SetSecurity(OpenApiOperation operation)
{
if (_insertRestriction == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
Expand Down Expand Up @@ -50,20 +50,18 @@ protected override void SetBasicInfo(OpenApiOperation operation)

/// <inheritdoc/>
protected override void SetRequestBody(OpenApiOperation operation)
{
{
OpenApiSchema schema = null;
if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
}

operation.RequestBody = new OpenApiRequestBody
{
Required = true,
Description = "New navigation property values",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = GetOpenApiSchema()
}
}
}
Content = GetContent(schema, _updateRestriction?.RequestContentTypes)
};

base.SetRequestBody(operation);
Expand Down Expand Up @@ -103,23 +101,5 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
AppendCustomParameters(operation, _updateRestriction.CustomQueryOptions, ParameterLocation.Query);
}
}

private OpenApiSchema GetOpenApiSchema()
{
if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
return EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
}

return new OpenApiSchema
{
UnresolvedReference = true,
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = NavigationProperty.ToEntityType().FullName()
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ internal class InsertRestrictionsType : IRecord
/// <returns>True/false.</returns>
public bool IsInsertable => Insertable == null || Insertable.Value == true;

/// <summary>
/// Lists the media types acceptable for the request content
/// </summary>
/// <remarks>This is not an official OASIS standard property.</remarks>
public IList<string> RequestContentTypes { get; private set; }

/// <summary>
/// Lists the media types acceptable for the response content
/// </summary>
/// <remarks>This is not an official OASIS standard property.</remarks>
public IList<string> ResponseContentTypes { get; private set; }

/// <summary>
/// Test the input navigation property do not allow deep insert.
/// </summary>
Expand Down Expand Up @@ -127,6 +139,12 @@ public void Initialize(IEdmRecordExpression record)

// LongDescription
LongDescription = record.GetString("LongDescription");

// RequestContentTypes
RequestContentTypes = record.GetCollection("RequestContentTypes");

// ResponseContentTypes
ResponseContentTypes = record.GetCollection("ResponseContentTypes");
}
}
}
Loading
Loading