Page 53 - MSDN Magazine, September 2019
P. 53
However, note that the code generated by the gRPC tooling is slightly different, as shown here:
public RepeatedField<string> OpponentTeam {get; set;}
Note, in fact, that any class generated from a gRPC message type T implements the members of the Google.ProtoBuf.IMes- sage<T> interface. The response message type should be designed to describe the actual data returned at each step of the streaming phase. So each reply must refer to an indi- vidual head-to-head response, between the primary team and one of the opponent teams specified in the array, like so:
message H2HMultiReply { H2HItem Team1 = 1; H2HItem Team2 = 2;
}
message H2HItem { string Name = 1; uint32 Won = 2;
}
The H2HItem message type indicates how many matches the given team has won against the other team specified in the request.
Before I move forward to look into the implementation of a stream method, let’s have a look at the dependencies required by the shared class library that embeds the proto definition. The Visual Studio project must reference the NuGet packages in Figure 1.
The project that includes the source .proto file must reference the Grpc.Tools package, as well as the Grpc.Net.Client (added in .NET Core 3.0 Preview 6) and Google.Protobuf packages required by any gRPC project (whether client, service or library). The tool- ing package is ultimately responsible for parsing the .proto file and generating any necessary C# classes at compile time. An item group block in the .csproj file instructs the tooling system on how to proceed. Here’s the code:
<ItemGroup>
<Protobuf Include="Protos\h2h.proto"
GrpcServices="Server, Client"
Generator="MSBuild:Compile" /> <Content Include="@(Protobuf)" />
<None Remove="@(Protobuf)" /> </ItemGroup>
The most relevant part of the ItemGroup block is the Protobuf node and in particular the GrpcServices attribute. The Server
Figure 2 Configuring the gRPC Service
token in its assigned string value indicates that the tooling must generate the service class for the prototyped interface. The Cli- ent token indicates that it’s also expected to create the base client class to invoke the service. With this done, the resulting DLL contains C# classes for the message types, base service class and client class. Both the service project and the client project (whether console, Web or desktop) only need to reference the prototype DLL in order to deal with the gRPC service.
Implementing the Service
The gRPC service is an ASP.NET Core proj- ect with some special configuration done in the startup class. In addition to the ASP.NET Core server platform and the prototype assembly, it references also the ASP.NET Core gRPC framework and the Google.Protobuf package. The Startup class adds the gRPC runtime service in the Configure method and appends gRPC endpoints in the Config- ureServices method, as shown in Figure 2.
The service class inherits from the base service class the tooling created based on the content of the .proto file, like so:
public class H2HService : Sample.H2H.H2HBase {
// Unary method Details
public override Task<H2HReply> Details(
Figure 1 The NuGet Dependencies of the Proto Shared Class Library
{ } ...
}
...
H2HRequest request, ServerCallContext context)
Unary methods like the Details method have a simpler signa- ture than stream methods. They return a Task<TReply> object and accept a TRequest object plus an instance of ServerCallContext to access the nitty-gritty details of the incoming request. A server- side stream method has an additional response stream parameter used by the implementation code to stream packets back. Figure 3 presents the implementation of the MultiRequest stream method.
As you can see, compared to classic unary methods, the stream method takes an additional parameter of type IServerStream- Writer<TReply>. This is the output stream the method will use to stream back results as they’re ready. In the code in Figure 3, the method enters in a loop for each of the operations requested (in this case, an array of teams to get past matches). It then streams back results as the query against a local/remote database or Web service returns. Once complete, the method returns and the underlying runtime environment closes the stream.
Writing a Client for a Stream Method
Inthesamplecode,theclientapplicationisaplainASP.NETCore 3.0 application. It holds references to the Google.Protobuf package and the Grpc.Net.Client package, plus the shared prototype library. The UI presents a button with some JavaScript attached that posts
public void ConfigureServices(IServiceCollection services) {
services.AddGrpc(); }
public void Configure(IApplicationBuilder app) {
// Some other code here ...
app.UseRouting(); app.UseEndpoints(endpoints => {
endpoints.MapGrpcService<H2HService>(); });
}
msdnmagazine.com
September 2019 45