From 15c6bc22aa3e841b5612490dbadee24767db4de9 Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Mon, 31 Aug 2015 11:06:00 -0700
Subject: [PATCH] update README.md

---
 examples/csharp/route_guide/README.md         | 115 +++++++-----------
 .../RouteGuideServer/RouteGuideImpl.cs        |   5 +-
 2 files changed, 50 insertions(+), 70 deletions(-)

diff --git a/examples/csharp/route_guide/README.md b/examples/csharp/route_guide/README.md
index ec9a0c048e..155877e62e 100644
--- a/examples/csharp/route_guide/README.md
+++ b/examples/csharp/route_guide/README.md
@@ -93,16 +93,16 @@ message Point {
 Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C# plugin.
 
 If you want to run this yourself, make sure you've installed protoc and gRPC C# plugin. The instructions vary based on your OS:
-- For Windows, the `Grpc.Tools` NuGet package contains the binaries you will need to generate the code.
+- For Windows, the `Grpc.Tools` and `Google.Protobuf` NuGet packages contain the binaries you will need to generate the code.
 - For Linux, make sure you've [installed gRPC C Core using Linuxbrew](https://github.com/grpc/grpc/tree/master/src/csharp#usage-linux-mono)
 - For MacOS, make sure you've [installed gRPC C Core using Homebrew](https://github.com/grpc/grpc/tree/master/src/csharp#usage-macos-mono)
 
 Once that's done, the following command can be used to generate the C# code.
 
-To generate the code on Windows, we use `protoc.exe` and `grpc_csharp_plugin.exe` binaries that are shipped with the `Grpc.Tools` NuGet package under the `tools` directory.
+To generate the code on Windows, we use `protoc.exe` from the `Google.Protobuf` NuGet package and `grpc_csharp_plugin.exe` from the `Grpc.Tools` NuGet package (both under the `tools` directory).
 Normally you would need to add the `Grpc.Tools` package to the solution yourself, but in this tutorial it has been already done for you. Following command should be run from the `csharp/route_guide` directory:
 ```
-> packages\Grpc.Tools.0.5.1\tools\protoc -I RouteGuide/protos --csharp_out=RouteGuide --grpc_out=RouteGuide --plugin=protoc-gen-grpc=packages\Grpc.Tools.0.5.1\tools\grpc_csharp_plugin.exe RouteGuide/protos/route_guide.proto
+> packages\Google.Protobuf.3.0.0-alpha4\tools\protoc -I RouteGuide/protos --csharp_out=RouteGuide --grpc_out=RouteGuide --plugin=protoc-gen-grpc=packages\Grpc.Tools.0.7.0\tools\grpc_csharp_plugin.exe RouteGuide/protos/route_guide.proto
 ```
 
 On Linux/MacOS, we rely on `protoc` and `grpc_csharp_plugin` being installed by Linuxbrew/Homebrew. Run this command from the route_guide directory:
@@ -143,7 +143,7 @@ public class RouteGuideImpl : RouteGuide.IRouteGuide
 `RouteGuideImpl` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`.
 
 ```csharp
-    public Task<Feature> GetFeature(Grpc.Core.ServerCallContext context, Point request)
+    public Task<Feature> GetFeature(Point request, Grpc.Core.ServerCallContext context)
     {
         return Task.FromResult(CheckFeature(request));
     }
@@ -159,27 +159,14 @@ Now let's look at something a bit more complicated - a streaming RPC. `ListFeatu
 
 ```csharp
     // in RouteGuideImpl
-    public async Task ListFeatures(Grpc.Core.ServerCallContext context, Rectangle request,
-	    Grpc.Core.IServerStreamWriter<Feature> responseStream)
+    public async Task ListFeatures(Rectangle request,
+        Grpc.Core.IServerStreamWriter<Feature> responseStream,
+        Grpc.Core.ServerCallContext context)
     {
-        int left = Math.Min(request.Lo.Longitude, request.Hi.Longitude);
-        int right = Math.Max(request.Lo.Longitude, request.Hi.Longitude);
-        int top = Math.Max(request.Lo.Latitude, request.Hi.Latitude);
-        int bottom = Math.Min(request.Lo.Latitude, request.Hi.Latitude);
-
-        foreach (var feature in features)
+        var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
+        foreach (var response in responses)
         {
-            if (!RouteGuideUtil.Exists(feature))
-            {
-                continue;
-            }
-
-            int lat = feature.Location.Latitude;
-            int lon = feature.Location.Longitude;
-            if (lon >= left && lon <= right && lat >= bottom && lat <= top)
-            {
-                await responseStream.WriteAsync(feature);
-            }
+            await responseStream.WriteAsync(response);
         }
     }
 ```
@@ -191,8 +178,8 @@ As you can see, here the request object is a `Rectangle` in which our client wan
 Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumerator](https://github.com/Reactive-Extensions/Rx.NET/blob/master/Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs), to read the stream of requests using the async method `MoveNext` and the `Current` property.
 
 ```csharp
-    public async Task<RouteSummary> RecordRoute(Grpc.Core.ServerCallContext context,
-	    Grpc.Core.IAsyncStreamReader<Point> requestStream)
+    public async Task<RouteSummary> RecordRoute(Grpc.Core.IAsyncStreamReader<Point> requestStream,
+        Grpc.Core.ServerCallContext context)
     {
         int pointCount = 0;
         int featureCount = 0;
@@ -205,21 +192,26 @@ Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumera
         {
             var point = requestStream.Current;
             pointCount++;
-            if (RouteGuideUtil.Exists(CheckFeature(point)))
+            if (CheckFeature(point).Exists())
             {
                 featureCount++;
             }
             if (previous != null)
             {
-                distance += (int) CalcDistance(previous, point);
+                distance += (int) previous.GetDistance(point);
             }
             previous = point;
         }
 
         stopwatch.Stop();
-        return RouteSummary.CreateBuilder().SetPointCount(pointCount)
-            .SetFeatureCount(featureCount).SetDistance(distance)
-            .SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build();
+        
+        return new RouteSummary
+        {
+            PointCount = pointCount,
+            FeatureCount = featureCount,
+            Distance = distance,
+            ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000)
+        };
     }
 ```
 
@@ -228,28 +220,17 @@ Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumera
 Finally, let's look at our bidirectional streaming RPC `RouteChat`.
 
 ```csharp
-    public async Task RouteChat(Grpc.Core.ServerCallContext context,
-	    Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream)
+    public async Task RouteChat(Grpc.Core.IAsyncStreamReader<RouteNote> requestStream,
+        Grpc.Core.IServerStreamWriter<RouteNote> responseStream,
+        Grpc.Core.ServerCallContext context,)
     {
         while (await requestStream.MoveNext())
-        {
+        {        
             var note = requestStream.Current;
-            List<RouteNote> notes = GetOrCreateNotes(note.Location);
-
-			List<RouteNote> prevNotes;
-            lock (notes)
-            {
-                prevNotes = new List<RouteNote>(notes);
-            }
-
+            List<RouteNote> prevNotes = AddNoteForLocation(note.Location, note);
             foreach (var prevNote in prevNotes)
             {
                 await responseStream.WriteAsync(prevNote);
-            }                
-                
-            lock (notes)
-            {
-                notes.Add(note);
             }
         }
     }
@@ -263,11 +244,12 @@ Once we've implemented all our methods, we also need to start up a gRPC server s
 
 ```csharp
 var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile);
-GrpcEnvironment.Initialize();
 
-Server server = new Server();
-server.AddServiceDefinition(RouteGuide.BindService(new RouteGuideImpl(features)));
-int port = server.AddListeningPort("localhost", 50052);
+Server server = new Server
+{
+    Services = { RouteGuide.BindService(new RouteGuideImpl(features)) },
+    Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
+};
 server.Start();
 
 Console.WriteLine("RouteGuide server listening on port " + port);
@@ -275,14 +257,13 @@ Console.WriteLine("Press any key to stop the server...");
 Console.ReadKey();
 
 server.ShutdownAsync().Wait();
-GrpcEnvironment.Shutdown();
 ```
 As you can see, we build and start our server using `Grpc.Core.Server` class. To do this, we:
 
 1. Create an instance of `Grpc.Core.Server`.
 1. Create an instance of our service implementation class `RouteGuideImpl`.
-3. Register our service implementation with the server using the `AddServiceDefinition` method and the generated method `RouteGuide.BindService`.
-2. Specify the address and port we want to use to listen for client requests using the `AddListeningPort` method.
+3. Register our service implementation by adding its service definition to `Services` collection (We obtain the service definition from the generated `RouteGuide.BindService` method).
+2. Specify the address and port we want to use to listen for client requests. This is done by adding `ServerPort` to `Ports` collection.
 4. Call `Start` on the server instance to start an RPC server for our service.
 
 <a name="client"></a>
@@ -294,19 +275,15 @@ In this section, we'll look at creating a C# client for our `RouteGuide` service
 
 To call service methods, we first need to create a *stub*.
 
-First, we need to create a gRPC client channel that will connect to gRPC server. Then, we use the `RouteGuide.NewStub` method of the `RouteGuide` class generated from our .proto.
+First, we need to create a gRPC client channel that will connect to gRPC server. Then, we use the `RouteGuide.NewClient` method of the `RouteGuide` class generated from our .proto.
 
 ```csharp
-GrpcEnvironment.Initialize();
+Channel channel = new Channel("127.0.0.1:50052", Credentials.Insecure)
+var client = new RouteGuideClient(RouteGuide.NewClient(channel));
 
-using (Channel channel = new Channel("127.0.0.1:50052"))
-{
-    var client = RouteGuide.NewStub(channel);
- 
-    // YOUR CODE GOES HERE
-}
+// YOUR CODE GOES HERE
 
-GrpcEnvironment.Shutdown();
+channel.ShutdownAsync().Wait();
 ```
 
 ### Calling service methods
@@ -319,7 +296,7 @@ gRPC C# also provides a synchronous method stub, but only for simple (single req
 Calling the simple RPC `GetFeature` in a synchronous way is nearly as straightforward as calling a local method.
 
 ```csharp
-Point request = Point.CreateBuilder().SetLatitude(409146138).SetLongitude(-746188906).Build();
+Point request = new Point { Latitude = 409146138, Longitude = -746188906 };
 Feature feature = client.GetFeature(request);
 ```
 
@@ -327,7 +304,7 @@ As you can see, we create and populate a request protocol buffer object (in our
 
 Alternatively, if you are in async context, you can call an asynchronous version of the method (and use `await` keyword to await the result):
 ```csharp
-Point request = Point.CreateBuilder().SetLatitude(409146138).SetLongitude(-746188906).Build();
+Point request = new Point { Latitude = 409146138, Longitude = -746188906 };
 Feature feature = await client.GetFeatureAsync(request);
 ```
 
@@ -349,17 +326,17 @@ using (var call = client.ListFeatures(request))
 ```
 
 The client-side streaming method `RecordRoute` is similar, except we use the property `RequestStream` to write the requests one by one using `WriteAsync` and eventually signal that no more request will be send using `CompleteAsync`. The method result can be obtained through the property
-`Result`.
+`ResponseAsync`.
 ```csharp
 using (var call = client.RecordRoute())
 {
     foreach (var point in points)
-	{
+    {
         await call.RequestStream.WriteAsync(point);
     }
     await call.RequestStream.CompleteAsync();
 
-    RouteSummary summary = await call.Result;
+    RouteSummary summary = await call.ResponseAsync;
 }
 ```
 
@@ -374,7 +351,7 @@ Finally, let's look at our bidirectional streaming RPC `RouteChat`. In this case
         {
             var note = call.ResponseStream.Current;
             Console.WriteLine("Received " + note);
-		}
+        }
     });
 
     foreach (RouteNote request in requests)
@@ -382,7 +359,7 @@ Finally, let's look at our bidirectional streaming RPC `RouteChat`. In this case
         await call.RequestStream.WriteAsync(request);
     }
     await call.RequestStream.CompleteAsync();
-	await responseReaderTask;
+    await responseReaderTask;
 }
 ```
 
diff --git a/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs b/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
index 65355631ec..fbe0f4471c 100644
--- a/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
+++ b/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
@@ -39,7 +39,10 @@ namespace Examples
         public async Task ListFeatures(Rectangle request, Grpc.Core.IServerStreamWriter<Feature> responseStream, Grpc.Core.ServerCallContext context)
         {
             var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
-            await responseStream.WriteAllAsync(responses);
+            foreach (var response in responses)
+            {
+                await responseStream.WriteAsync(response);
+            }
         }
 
         /// <summary>
-- 
GitLab