Page 54 - MSDN Magazine, September 2019
P. 54
Figure 3 A Server-Side Stream gRPC Service Method
Figure 4 Calling the gRPC Service
public override async Task MultiDetails( H2HMultiRequest request, IServerStreamWriter<H2HMultiReply> responseStream, ServerCallContext context)
{
// Loops through the batch of operations embedded // in the current request
foreach (var opponent in request.OpponentTeam)
{
// Grab H2H data to return
var h2h = GetHeadToHead_Internal(request.Team, opponent);
// Copy raw data into an official reply structure
// Raw data is captured in some way: an external REST service // or some local/remote database
var item1 = new H2HItem {
Name = h2h.Id1, Won = (uint) h2h.Record1}; var item2 = new H2HItem {
Name = h2h.Id2, Won = (uint) h2h.Record2};
var reply = new H2HMultiReply { Team1 = item1, Team2 = item2 };
// Write back via the output response stream
await responseStream.WriteAsync(reply); }
return; }
[HttpPost]
public async Task<IActionResult> Multi() {
// Call the RPC service
var serviceUrl = "http://localhost:50051";
AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var httpClient = new HttpClient() {BaseAddress = new Uri(serviceUrl) }; var client = GrpcClient.Create<H2H.H2HClient>(httpClient);
var request = new H2HMultiRequest() { Team = "AF-324" }; request.OpponentTeam.AddRange(new[] { "AW-367", "AD-683", "AF-510" }); var model = new H2HMultiViewModel();
using (var response = client.MultiDetails(request))
{
while (await response.ResponseStream.MoveNext())
{
var reply = response.ResponseStream.Current;
// Do something here ... }
}
return View(model); }
to a controller method. (Note that nothing stops you from using a classic HTML Form except that using Ajax to post might make it easier to receive notification of replies and update the UI in a smoother way.) Figure 4 presents the code.
packet from the gRPC service. What happens next depends on the client application. Overall, there are three distinct situations. One is when the client application has its own UI, but can wait
to collect the entire response before showing something fresh to the user. In this case, you load the data carried by the cur- rent reply object into the view model returned by the controller
It’s worth recalling that the port of the gRPC service depends on the Visual Studio project, while the client caller class is defined in the prototype library.
It’s worth recalling that the port of the gRPC service depends on the Visual Studio project, while the client caller class is defined in the prototype library. To prepare the request to a server-side streaming method, you don’t have to do anything more than just populate the input message type. As
mentioned, the OpponentTeam col-
lection is an enumerable .NET type
and can be populated with AddRange
or repeated calls to Add. The actual
type isn’t one of the .NET Core col-
lection types, but it’s still a collection
type despite being implemented in
the Google Protobuf package.
method. The second scenario is when there’s no UI (such as if the client is a working microservice). In this case, the received data is processed as soon as it’s available. Finally, in the third scenario the client application has its own responsive UI and is able to present
As a server-side method streams packets back until the end of the stream, the actual call to the meth- od returns a stream object. Next, the client code enumerates the packets waiting for the end of the response. Each iteration of the while loop in Figure 4 captures a single reply
Figure 5 The Sample Application in Action
46 msdn magazine
Cutting Edge