Skip to content

Commit 0b10e13

Browse files
authored
gRPC JSON transcoding: Fix request body OpenAPI (#47513)
1 parent 954d42b commit 0b10e13

File tree

6 files changed

+150
-3
lines changed

6 files changed

+150
-3
lines changed

src/Grpc/JsonTranscoding/src/Microsoft.AspNetCore.Grpc.Swagger/Internal/GrpcJsonTranscodingDescriptionProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private static ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint,
120120
{
121121
// If from a property, create model as property to get its XML comments.
122122
var identity = bodyDescriptor.PropertyInfo != null
123-
? ModelMetadataIdentity.ForProperty(bodyDescriptor.PropertyInfo, bodyDescriptor.Descriptor.ClrType, bodyDescriptor.PropertyInfo.DeclaringType!)
123+
? ModelMetadataIdentity.ForProperty(bodyDescriptor.PropertyInfo, bodyDescriptor.PropertyInfo.PropertyType, bodyDescriptor.PropertyInfo.DeclaringType!)
124124
: ModelMetadataIdentity.ForType(bodyDescriptor.Descriptor.ClrType);
125125

126126
// Or if from a parameter, create model as parameter to get its XML comments.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.AspNetCore.Grpc.Swagger.Tests.Infrastructure;
5+
using Microsoft.AspNetCore.Grpc.Swagger.Tests.Services;
6+
using Microsoft.OpenApi.Models;
7+
using Xunit.Abstractions;
8+
9+
namespace Microsoft.AspNetCore.Grpc.Swagger.Tests.Binding;
10+
11+
public class BodyTests
12+
{
13+
private readonly ITestOutputHelper _testOutputHelper;
14+
15+
public BodyTests(ITestOutputHelper testOutputHelper)
16+
{
17+
_testOutputHelper = testOutputHelper;
18+
}
19+
20+
[Fact]
21+
public void PostRepeated()
22+
{
23+
// Arrange & Act
24+
var swagger = OpenApiTestHelpers.GetOpenApiDocument<BodyService>(_testOutputHelper);
25+
26+
// Assert
27+
var path = swagger.Paths["/v1/body1"];
28+
Assert.True(path.Operations.TryGetValue(OperationType.Post, out var operation));
29+
30+
var bodySchema = operation.RequestBody.Content["application/json"].Schema;
31+
Assert.Null(bodySchema.Reference);
32+
Assert.Equal("array", bodySchema.Type);
33+
Assert.Equal("RequestBody", bodySchema.Items.Reference.Id);
34+
35+
var messageSchema = swagger.ResolveReference(bodySchema.Items.Reference);
36+
Assert.NotNull(messageSchema);
37+
}
38+
39+
[Fact]
40+
public void PostMap()
41+
{
42+
// Arrange & Act
43+
var swagger = OpenApiTestHelpers.GetOpenApiDocument<BodyService>(_testOutputHelper);
44+
45+
// Assert
46+
var path = swagger.Paths["/v1/body2"];
47+
Assert.True(path.Operations.TryGetValue(OperationType.Post, out var operation));
48+
49+
var bodySchema = operation.RequestBody.Content["application/json"].Schema;
50+
Assert.Null(bodySchema.Reference);
51+
Assert.Equal("object", bodySchema.Type);
52+
Assert.Equal("integer", bodySchema.AdditionalProperties.Type);
53+
}
54+
55+
[Fact]
56+
public void PostMessage()
57+
{
58+
// Arrange & Act
59+
var swagger = OpenApiTestHelpers.GetOpenApiDocument<BodyService>(_testOutputHelper);
60+
61+
// Assert
62+
var path = swagger.Paths["/v1/body3"];
63+
Assert.True(path.Operations.TryGetValue(OperationType.Post, out var operation));
64+
65+
var bodySchema = operation.RequestBody.Content["application/json"].Schema;
66+
Assert.Equal("RequestBody", bodySchema.Reference.Id);
67+
}
68+
69+
[Fact]
70+
public void PostRoot()
71+
{
72+
// Arrange & Act
73+
var swagger = OpenApiTestHelpers.GetOpenApiDocument<BodyService>(_testOutputHelper);
74+
75+
// Assert
76+
var path = swagger.Paths["/v1/body4"];
77+
Assert.True(path.Operations.TryGetValue(OperationType.Post, out var operation));
78+
79+
var bodySchema = operation.RequestBody.Content["application/json"].Schema;
80+
Assert.Equal("RequestOne", bodySchema.Reference.Id);
81+
}
82+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using Microsoft.OpenApi.Models;
77
using Xunit.Abstractions;
88

9-
namespace Microsoft.AspNetCore.Grpc.Swagger.Tests.Parameters;
9+
namespace Microsoft.AspNetCore.Grpc.Swagger.Tests.Binding;
1010

1111
public class ParametersTests
1212
{

src/Grpc/JsonTranscoding/test/Microsoft.AspNetCore.Grpc.Swagger.Tests/Microsoft.AspNetCore.Grpc.Swagger.Tests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
44
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -7,6 +7,7 @@
77

88
<ItemGroup>
99
<Protobuf Include="Proto\counter.proto" GrpcServices="Both" />
10+
<Protobuf Include="Proto\body.proto" GrpcServices="Both" />
1011
<Protobuf Include="Proto\parameters.proto" GrpcServices="Both" />
1112
<Protobuf Include="Proto\xmldoc.proto" GrpcServices="Both" />
1213
<Protobuf Include="Proto\greeter.proto" GrpcServices="Both" />
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
syntax = "proto3";
5+
6+
package body;
7+
8+
import "google/api/annotations.proto";
9+
10+
// Add go_package to keep protoc happy when testing generating OpenAPI from commandline.
11+
option go_package = "github.com/dotnet/aspnetcore/swagger";
12+
13+
// HttpRule: https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#google.api.HttpRule
14+
15+
service Body {
16+
rpc DemoBodyOne (RequestOne) returns (BodyParamResponse) {
17+
option (google.api.http) = {
18+
post: "/v1/body1",
19+
body: "parameter_one"
20+
};
21+
}
22+
rpc DemoBodyTwo (RequestOne) returns (BodyParamResponse) {
23+
option (google.api.http) = {
24+
post: "/v1/body2",
25+
body: "parameter_two"
26+
};
27+
}
28+
rpc DemoBodyThree (RequestOne) returns (BodyParamResponse) {
29+
option (google.api.http) = {
30+
post: "/v1/body3",
31+
body: "parameter_three"
32+
};
33+
}
34+
rpc DemoBodyFour (RequestOne) returns (BodyParamResponse) {
35+
option (google.api.http) = {
36+
post: "/v1/body4",
37+
body: "*"
38+
};
39+
}
40+
}
41+
42+
message RequestOne {
43+
repeated RequestBody parameter_one = 1;
44+
map<int32, int32> parameter_two = 2;
45+
RequestBody parameter_three = 3;
46+
}
47+
48+
message RequestBody {
49+
string request_body = 1;
50+
}
51+
52+
message BodyParamResponse {
53+
string message = 1;
54+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Params;
5+
6+
namespace Microsoft.AspNetCore.Grpc.Swagger.Tests.Services;
7+
8+
public class BodyService : Body.Body.BodyBase
9+
{
10+
}

0 commit comments

Comments
 (0)