Skip to content

Commit 079f8ea

Browse files
authored
Provides support for using the range of response status code 2XX (#215)
* UseHTTPStatusCodeClass2XX as a setting to rep. all status codes 200-299 * Implement UseStatusCodeClass2XX setting when generating responses * Update tests to validate use of the setting: UseHTTPStatusCodeClass2XX * Rename property * Update tests * Add schema to responses with 2XX status code; return 204 status code for actions/functions * Rename field variables appropriately * Update csproj with project release notes; fix missing comma
1 parent fba1c33 commit 079f8ea

File tree

49 files changed

+604
-427
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+604
-427
lines changed

src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ internal static class Constants
2525
/// </summary>
2626
public static string ApplicationOctetStreamMediaType = "application/octet-stream";
2727

28+
/// <summary>
29+
/// Status code class: 2XX
30+
/// </summary>
31+
public static string StatusCodeClass2XX = "2XX";
32+
2833
/// <summary>
2934
/// Status code: 200
3035
/// </summary>

src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using Microsoft.OpenApi.Models;
77
using Microsoft.OpenApi.OData.Generator;
8+
using System.Collections.Generic;
89

910
namespace Microsoft.OpenApi.OData.Common;
1011

@@ -20,7 +21,8 @@ public static class OpenApiOperationExtensions
2021
/// <param name="operation">The operation.</param>
2122
/// <param name="settings">The settings.</param>
2223
/// <param name="addNoContent">Whether to add a 204 no content response.</param>
23-
public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, bool addNoContent = false)
24+
/// <param name="schema">Optional: The OpenAPI schema of the response.</param>
25+
public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, bool addNoContent = false, OpenApiSchema schema = null)
2426
{
2527
if (operation == null) {
2628
throw Error.ArgumentNull(nameof(operation));
@@ -34,9 +36,29 @@ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiCon
3436
operation.Responses = new();
3537
}
3638

37-
if(addNoContent)
39+
if (addNoContent)
3840
{
39-
operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse());
41+
if (settings.UseSuccessStatusCodeRange && schema != null)
42+
{
43+
OpenApiResponse response = new()
44+
{
45+
Content = new Dictionary<string, OpenApiMediaType>
46+
{
47+
{
48+
Constants.ApplicationJsonMediaType,
49+
new OpenApiMediaType
50+
{
51+
Schema = schema
52+
}
53+
}
54+
}
55+
};
56+
operation.Responses.Add(Constants.StatusCodeClass2XX, response);
57+
}
58+
else
59+
{
60+
operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse());
61+
}
4062
}
4163

4264
if(settings.ErrorResponsesAsDefault)

src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp
205205
}
206206
}
207207
};
208-
responses.Add(Constants.StatusCode200, response);
208+
responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, response);
209209
}
210210

211211
if (context.Settings.ErrorResponsesAsDefault)

src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@
1515
<TargetFrameworks>netstandard2.0</TargetFrameworks>
1616
<PackageId>Microsoft.OpenApi.OData</PackageId>
1717
<SignAssembly>true</SignAssembly>
18-
<Version>1.0.11-preview1</Version>
18+
<Version>1.0.11-preview2</Version>
1919
<Description>This package contains the codes you need to convert OData CSDL to Open API Document of Model.</Description>
2020
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
2121
<PackageTags>Microsoft OpenApi OData EDM</PackageTags>
2222
<RepositoryUrl>https://github.com/Microsoft/OpenAPI.NET.OData</RepositoryUrl>
2323
<PackageReleaseNotes>
24-
- Adds list of all derived types for discriminator mapping #219
2524
- Fixes reading restriction annotations for entity types defining navigation properties #220
2625
- Enables configuring appending bound operations on derived types #221
2726
- Add error ranges for OData actions when ErrorResponsesAsDefault is set to false #218
27+
- Fixes missing bound operations on some navigation property paths #201
28+
- Provides support for using success status code range 2XX #153
2829
</PackageReleaseNotes>
2930
<AssemblyName>Microsoft.OpenApi.OData.Reader</AssemblyName>
3031
<AssemblyOriginatorKeyFile>..\..\tool\Microsoft.OpenApi.OData.snk</AssemblyOriginatorKeyFile>

src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ public string PathPrefix
253253
/// </summary>
254254
public bool AppendBoundOperationsOnDerivedTypeCastSegments { get; set; } = false;
255255

256+
/// <summary>
257+
/// Gets/Sets a value indicating whether or not to use the HTTP success status code range 2XX
258+
/// to represent all response codes between 200 - 299.
259+
/// </summary>
260+
public bool UseSuccessStatusCodeRange { get; set; } = false;
261+
256262
internal OpenApiConvertSettings Clone()
257263
{
258264
var newSettings = new OpenApiConvertSettings
@@ -294,7 +300,8 @@ internal OpenApiConvertSettings Clone()
294300
RequireRestrictionAnnotationsToGenerateComplexPropertyPaths = this.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths,
295301
ExpandDerivedTypesNavigationProperties = this.ExpandDerivedTypesNavigationProperties,
296302
CustomXMLAttributesMapping = this.CustomXMLAttributesMapping,
297-
AppendBoundOperationsOnDerivedTypeCastSegments = this.AppendBoundOperationsOnDerivedTypeCastSegments
303+
AppendBoundOperationsOnDerivedTypeCastSegments = this.AppendBoundOperationsOnDerivedTypeCastSegments,
304+
UseSuccessStatusCodeRange = this.UseSuccessStatusCodeRange
298305
};
299306

300307
return newSettings;

src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,13 @@ internal class ComplexPropertyGetOperationHandler : ComplexPropertyBaseOperation
2020
/// <inheritdoc />
2121
public override OperationType OperationType => OperationType.Get;
2222

23-
/// <summary>
24-
/// Gets/Sets the <see cref="ReadRestrictionsType"/>
25-
/// </summary>
26-
private ReadRestrictionsType ReadRestrictions { get; set; }
23+
private ReadRestrictionsType _readRestrictions;
2724

2825
protected override void Initialize(ODataContext context, ODataPath path)
2926
{
3027
base.Initialize(context, path);
3128

32-
ReadRestrictions = Context.Model.GetRecord<ReadRestrictionsType>(ComplexPropertySegment.Property, CapabilitiesConstants.ReadRestrictions);
29+
_readRestrictions = Context.Model.GetRecord<ReadRestrictionsType>(ComplexPropertySegment.Property, CapabilitiesConstants.ReadRestrictions);
3330
}
3431

3532
/// <inheritdoc/>
@@ -45,8 +42,8 @@ protected override void SetBasicInfo(OpenApiOperation operation)
4542

4643
// Summary and Description
4744
string placeHolder = $"Get {ComplexPropertySegment.Property.Name} property value";
48-
operation.Summary = ReadRestrictions?.Description ?? placeHolder;
49-
operation.Description = ReadRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(ComplexPropertySegment.Property);
45+
operation.Summary = _readRestrictions?.Description ?? placeHolder;
46+
operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(ComplexPropertySegment.Property);
5047

5148
base.SetBasicInfo(operation);
5249
}
@@ -155,7 +152,7 @@ private void SetCollectionResponse(OpenApiOperation operation)
155152
operation.Responses = new OpenApiResponses
156153
{
157154
{
158-
Constants.StatusCode200,
155+
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
159156
new OpenApiResponse
160157
{
161158
UnresolvedReference = true,
@@ -187,7 +184,7 @@ private void SetSingleResponse(OpenApiOperation operation)
187184
operation.Responses = new OpenApiResponses
188185
{
189186
{
190-
Constants.StatusCode200,
187+
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
191188
new OpenApiResponse
192189
{
193190
Description = "Result entities",
@@ -207,29 +204,29 @@ private void SetSingleResponse(OpenApiOperation operation)
207204
}
208205
protected override void SetSecurity(OpenApiOperation operation)
209206
{
210-
if (ReadRestrictions?.Permissions == null)
207+
if (_readRestrictions?.Permissions == null)
211208
{
212209
return;
213210
}
214211

215-
operation.Security = Context.CreateSecurityRequirements(ReadRestrictions.Permissions).ToList();
212+
operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions).ToList();
216213
}
217214

218215
protected override void AppendCustomParameters(OpenApiOperation operation)
219216
{
220-
if (ReadRestrictions == null)
217+
if (_readRestrictions == null)
221218
{
222219
return;
223220
}
224221

225-
if (ReadRestrictions.CustomHeaders != null)
222+
if (_readRestrictions.CustomHeaders != null)
226223
{
227-
AppendCustomParameters(operation, ReadRestrictions.CustomHeaders, ParameterLocation.Header);
224+
AppendCustomParameters(operation, _readRestrictions.CustomHeaders, ParameterLocation.Header);
228225
}
229226

230-
if (ReadRestrictions.CustomQueryOptions != null)
227+
if (_readRestrictions.CustomQueryOptions != null)
231228
{
232-
AppendCustomParameters(operation, ReadRestrictions.CustomQueryOptions, ParameterLocation.Query);
229+
AppendCustomParameters(operation, _readRestrictions.CustomQueryOptions, ParameterLocation.Query);
233230
}
234231
}
235232
}

src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,12 @@ protected override void Initialize(ODataContext context, ODataPath path)
2626
throw new InvalidOperationException("OData conventions do not support POSTing to a complex property that is not a collection.");
2727
}
2828

29-
InsertRestrictions = Context.Model.GetRecord<InsertRestrictionsType>(ComplexPropertySegment.Property, CapabilitiesConstants.InsertRestrictions);
29+
_insertRestrictions = Context.Model.GetRecord<InsertRestrictionsType>(ComplexPropertySegment.Property, CapabilitiesConstants.InsertRestrictions);
3030
}
3131
/// <inheritdoc />
3232
public override OperationType OperationType => OperationType.Post;
3333

34-
/// <summary>
35-
/// Gets/Sets the <see cref="InsertRestrictionsType"/>
36-
/// </summary>
37-
private InsertRestrictionsType InsertRestrictions { get; set; }
34+
private InsertRestrictionsType _insertRestrictions;
3835

3936
/// <inheritdoc/>
4037
protected override void SetBasicInfo(OpenApiOperation operation)
@@ -48,8 +45,8 @@ protected override void SetBasicInfo(OpenApiOperation operation)
4845

4946
// Summary and Description
5047
string placeHolder = $"Sets a new value for the collection of {ComplexPropertySegment.ComplexType.Name}.";
51-
operation.Summary = InsertRestrictions?.Description ?? placeHolder;
52-
operation.Description = InsertRestrictions?.LongDescription;
48+
operation.Summary = _insertRestrictions?.Description ?? placeHolder;
49+
operation.Description = _insertRestrictions?.LongDescription;
5350

5451
base.SetBasicInfo(operation);
5552
}
@@ -72,20 +69,7 @@ protected override void SetParameters(OpenApiOperation operation)
7269
}
7370
/// <inheritdoc/>
7471
protected override void SetRequestBody(OpenApiOperation operation)
75-
{
76-
OpenApiSchema schema = new()
77-
{
78-
Type = "array",
79-
Items = new OpenApiSchema
80-
{
81-
UnresolvedReference = true,
82-
Reference = new OpenApiReference
83-
{
84-
Type = ReferenceType.Schema,
85-
Id = ComplexPropertySegment.ComplexType.FullName()
86-
}
87-
}
88-
};
72+
{
8973
operation.RequestBody = new OpenApiRequestBody
9074
{
9175
Required = true,
@@ -95,7 +79,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
9579
{
9680
Constants.ApplicationJsonMediaType, new OpenApiMediaType
9781
{
98-
Schema = schema
82+
Schema = GetOpenApiSchema()
9983
}
10084
}
10185
}
@@ -106,35 +90,52 @@ protected override void SetRequestBody(OpenApiOperation operation)
10690
/// <inheritdoc/>
10791
protected override void SetResponses(OpenApiOperation operation)
10892
{
109-
operation.AddErrorResponses(Context.Settings, true);
93+
operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema());
11094
base.SetResponses(operation);
11195
}
11296

11397
protected override void SetSecurity(OpenApiOperation operation)
11498
{
115-
if (InsertRestrictions?.Permissions == null)
99+
if (_insertRestrictions?.Permissions == null)
116100
{
117101
return;
118102
}
119103

120-
operation.Security = Context.CreateSecurityRequirements(InsertRestrictions.Permissions).ToList();
104+
operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions).ToList();
121105
}
122106

123107
protected override void AppendCustomParameters(OpenApiOperation operation)
124108
{
125-
if (InsertRestrictions == null)
109+
if (_insertRestrictions == null)
126110
{
127111
return;
128112
}
129113

130-
if (InsertRestrictions.CustomQueryOptions != null)
114+
if (_insertRestrictions.CustomQueryOptions != null)
131115
{
132-
AppendCustomParameters(operation, InsertRestrictions.CustomQueryOptions, ParameterLocation.Query);
116+
AppendCustomParameters(operation, _insertRestrictions.CustomQueryOptions, ParameterLocation.Query);
133117
}
134118

135-
if (InsertRestrictions.CustomHeaders != null)
119+
if (_insertRestrictions.CustomHeaders != null)
136120
{
137-
AppendCustomParameters(operation, InsertRestrictions.CustomHeaders, ParameterLocation.Header);
121+
AppendCustomParameters(operation, _insertRestrictions.CustomHeaders, ParameterLocation.Header);
138122
}
139123
}
124+
125+
private OpenApiSchema GetOpenApiSchema()
126+
{
127+
return new()
128+
{
129+
Type = "array",
130+
Items = new OpenApiSchema
131+
{
132+
UnresolvedReference = true,
133+
Reference = new OpenApiReference
134+
{
135+
Type = ReferenceType.Schema,
136+
Id = ComplexPropertySegment.ComplexType.FullName()
137+
}
138+
}
139+
};
140+
}
140141
}

0 commit comments

Comments
 (0)