Skip to content

Commit

Permalink
Add ProtoStatus example (#2273)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK authored Jan 8, 2024
1 parent 934bcec commit abaaf44
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 28 deletions.
20 changes: 20 additions & 0 deletions examples/Error/Client/Client.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Protobuf Include="..\Proto\greet.proto" GrpcServices="Client" Link="Protos\greet.proto" />

<PackageReference Include="Google.Protobuf" VersionOverride="3.25.0" />
<PackageReference Include="Grpc.Tools" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<!-- Project references required until Grpc.StatusProto is on nuget.org -->
<ProjectReference Include="..\..\..\src\Grpc.Net.Client\Grpc.Net.Client.csproj" />
<ProjectReference Include="..\..\..\src\Grpc.StatusProto\Grpc.StatusProto.csproj" />
</ItemGroup>
</Project>
56 changes: 56 additions & 0 deletions examples/Error/Client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using Google.Rpc;
using Greet;
using Grpc.Core;
using Grpc.Net.Client;

using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);

Console.WriteLine("Hello world app");
Console.WriteLine("===============");

while (true)
{
Console.WriteLine();

Console.Write("Enter name: ");
var name = Console.ReadLine();

try
{
var reply = await client.SayHelloAsync(new HelloRequest { Name = name });
Console.WriteLine("Greeting: " + reply.Message);
}
catch (RpcException ex)
{
Console.WriteLine($"Server error: {ex.Status.Detail}");

var badRequest = ex.GetRpcStatus()?.GetDetail<BadRequest>();
if (badRequest != null)
{
foreach (var fieldViolation in badRequest.FieldViolations)
{
Console.WriteLine($"Field: {fieldViolation.Field}");
Console.WriteLine($"Description: {fieldViolation.Description}");
}
}
}
}
61 changes: 61 additions & 0 deletions examples/Error/Error.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34004.107
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{534AC5F8-2DF2-40BD-87A5-B3D8310118C4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{48A1D3BC-A14B-436A-8822-6DE2BEF8B747}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.StatusProto", "..\..\src\Grpc.StatusProto\Grpc.StatusProto.csproj", "{08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core.Api", "..\..\src\Grpc.Core.Api\Grpc.Core.Api.csproj", "{E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Net.Client", "..\..\src\Grpc.Net.Client\Grpc.Net.Client.csproj", "{E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Net.Common", "..\..\src\Grpc.Net.Common\Grpc.Net.Common.csproj", "{23678E37-37D4-4543-9961-403B3760862B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.AspNetCore.Server", "..\..\src\Grpc.AspNetCore.Server\Grpc.AspNetCore.Server.csproj", "{A1368174-6D27-49F1-B6DC-F1868CAE000F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Release|Any CPU.Build.0 = Release|Any CPU
{48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Release|Any CPU.Build.0 = Release|Any CPU
{08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Release|Any CPU.Build.0 = Release|Any CPU
{E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Release|Any CPU.Build.0 = Release|Any CPU
{E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Release|Any CPU.Build.0 = Release|Any CPU
{23678E37-37D4-4543-9961-403B3760862B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23678E37-37D4-4543-9961-403B3760862B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23678E37-37D4-4543-9961-403B3760862B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23678E37-37D4-4543-9961-403B3760862B}.Release|Any CPU.Build.0 = Release|Any CPU
{A1368174-6D27-49F1-B6DC-F1868CAE000F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1368174-6D27-49F1-B6DC-F1868CAE000F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1368174-6D27-49F1-B6DC-F1868CAE000F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1368174-6D27-49F1-B6DC-F1868CAE000F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D22B3129-3BFB-41FA-9FCE-E45EBEF8C2DD}
EndGlobalSection
EndGlobal
33 changes: 33 additions & 0 deletions examples/Error/Proto/greet.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package greet;

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings
message HelloReply {
string message = 1;
}
54 changes: 54 additions & 0 deletions examples/Error/Server/GrpcValidation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using System.Runtime.CompilerServices;
using Google.Protobuf.WellKnownTypes;
using Google.Rpc;
using Grpc.Core;

namespace Server;

public static class GrpcValidation
{
public static void ArgumentNotNullOrEmpty(string value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
{
if (string.IsNullOrEmpty(value))
{
var status = new Google.Rpc.Status
{
Code = (int)Code.InvalidArgument,
Message = "Bad request",
Details =
{
Any.Pack(new BadRequest
{
FieldViolations =
{
new BadRequest.Types.FieldViolation
{
Field = paramName,
Description = "Value is null or empty"
}
}
})
}
};
throw status.ToRpcException();
}
}
}
27 changes: 27 additions & 0 deletions examples/Error/Server/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using Server;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();

var app = builder.Build();
app.MapGrpcService<GreeterService>();

app.Run();
12 changes: 12 additions & 0 deletions examples/Error/Server/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"Server": {
"commandName": "Project",
"launchBrowser": false,
"applicationUrl": "https://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
20 changes: 20 additions & 0 deletions examples/Error/Server/Server.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Protobuf Include="..\Proto\greet.proto" GrpcServices="Server" Link="Protos\greet.proto" />

<PackageReference Include="Google.Protobuf" VersionOverride="3.25.0" />
<PackageReference Include="Grpc.Tools" />
</ItemGroup>

<ItemGroup>
<!-- Project references required until Grpc.StatusProto is on nuget.org -->
<ProjectReference Include="..\..\..\src\Grpc.AspNetCore.Server\Grpc.AspNetCore.Server.csproj" />
<ProjectReference Include="..\..\..\src\Grpc.StatusProto\Grpc.StatusProto.csproj" />
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions examples/Error/Server/Services/GreeterService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using Greet;
using Grpc.Core;

namespace Server;

public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
GrpcValidation.ArgumentNotNullOrEmpty(request.Name);

return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
}
}
10 changes: 10 additions & 0 deletions examples/Error/Server/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Grpc": "Information",
"Microsoft": "Information"
}
}
}
13 changes: 13 additions & 0 deletions examples/Error/Server/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"AllowedHosts": "*",
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"
}
}
}
Loading

0 comments on commit abaaf44

Please sign in to comment.