Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Updated README.md
  • Loading branch information
tonydnewell committed Jul 25, 2023
commit ef2ec28623d721ad38204914335485596467a801
86 changes: 81 additions & 5 deletions src/Grpc.StatusProto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,23 @@ returned in the trailing response metadata. Setting and reading this metadata i

The server side uses C#'s Object and Collection initializer syntax. The avoids the needs to a *builder* API to be developed.

The server returns an error by throwing an `RpcException` that contains metadata with key `"grpc-status-details-bin"` and value that is a serialized `Google.Rpc.Status`.
There are two ways that the server can return an error status:
- by throwing an `RpcException` that contains the details of the status.
- by explicitly set the `Status` and `ResponseTrailers` in the `ServerCallContext`
before returning.

There are examples of both methods below. In a .NET client the result will always be
an exception received by the client no matter which of the above methods the server
implements.

The `Google.Rpc.Status` can be created and initialized using C#'s Object and Collection initializer syntax. To add messages to the `Details` repeated field, wrap each one in `Any.Pack()` - see example below.

The `Google.Rpc.Status` extension method `ToRpcException` creates the appropriate `RpcException` from the status.

Example:
The `Grpc.Core.Metadata` extension method `SetRpcStatus` adds a binary representation of the status to the metadata.


Example - throwing a RcpException:
```C#
throw new Google.Rpc.Status
{
Expand All @@ -47,8 +57,8 @@ throw new Google.Rpc.Status
{
Any.Pack(new ErrorInfo
{
Domain = "Rich Error Model Demo",
Reason = "Simple error requested in the demo"
Domain = "error example",
Reason = "some reason"
}),
Any.Pack(new RequestInfo
{
Expand All @@ -58,6 +68,25 @@ throw new Google.Rpc.Status
}
}.ToRpcException();
```
Example - setting the status and response trailers instead of throwing an exception:
```C#
context.Status = new Grpc.Core.Status(StatusCode.Internal, "Some detail");
context.ResponseTrailers.SetRpcStatus(new Google.Rpc.Status
{
Code = (int)StatusCode.NotFound,
Message = "Simple error message",
Details =
{
Any.Pack(new ErrorInfo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: There are Google-internal proposals around the use of ErrorInfo; I'm checking on the status of those, but they could affect the preferred layout for the richer error model.

{
Domain = "error example",
Reason = "some reason"
})
}
});

return Task.FromResult( /* ... */ );
```

## Client Side

Expand Down Expand Up @@ -173,7 +202,54 @@ and [error_details.proto](https://github.com/googleapis/googleapis/blob/master/g
files are not currently provided in any NuGet packages. The text for those proto files can be copied from
the given links and included in your project.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: reword "The text for those proto files can be copied from
the given links and included in your project."

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting... do you think it would be beneficial to ship them in Google.Api.CommonProtos? I wouldn't be averse to that, but I'd need to consult the rest of the team.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, I'd say this wouldn't help much. I'd probably help if we had a general mechanism for shipping .proto file in nuget packages and Grpc.Tools could autogenerate source code for them (see #183), but we currently don't have that.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it happens, we had a feature request for that last week: googleapis/gax-dotnet#715
@jtattermusch If you believe it wouldn't actually help much, please could you comment on that issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is on my list to document a standard way/best practices for shipping proto files in NuGet packages so that Grpc.Tools can easily pick them up. Basically what @JamesNK does in the Microsoft.AspNetCore.Grpc.JsonTranscoding package.


*TODO* example C# code to follow
Example server code fragment:
```C#
while (await requestStream.MoveNext())
{
var request = requestStream.Current;
var response = new WidgetRsp();

// ... process the request ...

// to return an error
if (error)
{
response.Status = new Google.Rpc.Status { /* ... */ };
} else
{
response.WidgetDetails = "the details";
}
}
```

Example client code fragment:
```C#

// reading the responses
var responseReaderTask = Task.Run(async () =>
{
while (await call.ResponseStream.MoveNext())
{
var rsp = call.ResponseStream.Current;
switch (rsp.MessageCase)
{
case WidgetRsp.MessageOneofCase.WidgetDetails:
// ... processes the details ...
break;
case WidgetRsp.MessageOneofCase.Status:
// ... handle the error ...
break;
}
}
});

// sending the requests
foreach (var request in requests)
{
await call.RequestStream.WriteAsync(request);
}
```


## See also
* [Richer error model](https://grpc.io/docs/guides/error/#richer-error-model)
Expand Down