Build gRPC Client with .NET Core

In this post series we have seen how to build a simple gRPC request/reply service and a gRPC server streaming service by using .NET Core and the new grpc-dotnet, the managed library entirely written in C#. Now it’s the time to create and build a .NET gRPC client. And it’s really easy to do.

Create and configure our client project

First of all, we need to create a client project. For the purpose of this article, a simple console project will be enough. So, you can open the terminal, go to your preferred folder and execute the following command:

dotnet new console -o GrpcClient

Then go to the folder just created and add the necessary reference with the following commands:

dotnet add package Google.Protobuf
dotnet add package Grpc.Net.Client
dotnet add package Grpc.Tools

Now, we can create the bookshelf.proto file (full code available on my github repository:

syntax = "proto3";

option csharp_namespace = "BookshelfService";

package BookshelfService;

// The bookshelf service definition.
service BookService {
  // Get full list of books
  rpc GetAllBooks (AllBooksRequest) returns (stream AllBooksReply);
  // Save a Book
  rpc Save (NewBookRequest) returns (NewBookReply);
}

// The request message containing the book's title and description.
message AllBooksRequest {
  int32 itemsPerPage = 1;
}

// The request message containing the book's title and description.
message AllBooksReply {
  repeated Book Books = 1;
}

message Book {
  string title = 1;
  string description = 2;
}

// The request message containing the book's title and description.
message NewBookRequest {
  string title = 1;
  string description = 2;
}

// The response message containing the book id.
message NewBookReply {
  string id = 1;
}

We can then add the just created file to the project by using dotnet-grpc CLI. If you haven’t installed yet, execute the following command:

dotnet tool install -g dotnet-grpc

then add the bookshelf.proto to the client project:

dotnet grpc add-file bookshelf.proto --services Client

Finally, be sure to set the right GrpcService value of the Protobuf element in your .csproj file:

You can set the GrpcService attribute to decide the kind of grpc generated code. The accepted values are: Both, Client, Default, None, Server.

<ItemGroup>
  <Protobuf Include="..\Protos\bookshelf.proto" GrpcServices="Client" />
</ItemGroup>

Let’s start coding

Calling a Grpc Service is a very simple operation. Just create the channel, connect to the service endpoint, and then pass to the generated client as a constructor parameter. Now you can use the client instance to invoke the service methods:

using (var channel = GrpcChannel.ForAddress("http://localhost:5000"))
{
    var request = new NewBookRequest();
    request.Title = "1984";
    request.Description = "A George Orwell novel";

    var client =  new BookService.BookServiceClient(channel);
    client.Save(request);
}

NOTE: if you are on macOs, HTTP/2 on TLS is still not supported, so you need to deactivate it by using the following instruction before connect to the service: AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

Enjoy!

check full code on github

Server streaming with .NET Core gRPC service

In the first post of this .NET Core gRPC services, we have seen how to build a simple request-reply service by using .NET Core 3 and the brand new grpc-dotnet library entirely written in C#.

Now, it’s time to extend our scenario by exploring the next kind of service: server streaming.

NOTE: Remember that gRPC offers four kinds of service: request-reply, server streaming, client streaming, and bidirectional streaming. We’ll see the others in dedicated posts

Server Streaming Scenarios

First of all, what is server streaming? This is an excerpt the gRPC site:

Server streaming RPCs where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. gRPC guarantees message ordering within an individual RPC call.

Typically, server streaming may be useful when you have a set of data that needs to be continuously send to the client while the server is still working on that. Let me explain with some example: imagine you need to send back a list of items. Instead of sending a full list, with bad performance, you can send back a block of n items per message, allowing the client start its operations asynchronously. This is a very basic usage of server streaming.

Ok, now we can start coding

Based on the BookshelfService implemented in the previous post and available on my github repository, we must update the bookshelf.proto by adding a new service called GetAllBooks and the related AllBooksRequest and AllBooksReply. That service will return the full list of books from our shelf:

// The bookshelf service definition
service BookService {
  // Get full list of books
  rpc GetAllBooks (AllBooksRequest) returns (stream AllBooksReply);
}

// The Request message containing specific parameters
message AllBooksRequest {
  int32 itemsPerPage = 1;
}

// The Reply message containing the book list
message AllBooksReply {
  repeated Book Books = 1;
}

// The Book message represents a book instance
message Book {
  string title = 1;
  string description = 2;
}

After changing the .proto file, now you’ll be able to override the GetAllBooks method in the BookshelfService class to implement the server-side logic:

public override async Task GetAllBooks(AllBooksRequest request, IServerStreamWriter<AllBooksReply> responseStream, ServerCallContext context)
{
    var pageIndex = 0;
    while (!context.CancellationToken.IsCancellationRequested)
    {
        var books = BooksManager.ReadAll(++pageIndex, request.ItemsPerPage);
        if (!books.Any())
        {
            break;
        }

        var reply = new AllBooksReply();
        reply.Books.AddRange(books);
        await responseStream.WriteAsync(reply);
    }
}

Finally, we can run the service with the dotnet run command and test it with BloomRPC:

gRPC Server Streaming

In the next post we’ll see how to create the client for the server streaming service type.

Enjoy!

check full code on github

HTTP/2 over TLS is not supported on macOS due to missing ALPN support

If you are working with .NET Core on MacOS, you’ll probably get the following exception:

System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.

This happens because at the moment Kestrel doesn’t support HTTP/2 with TLS on macOS and older Windows versions such as Windows 7. To work around this issue, you have to disable TLS. Open your Program.cs file and update the CreateHostBuilder with the following lines:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(options =>
            {
                options.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2);
            });
            webBuilder.UseStartup<Startup>();
        });

That’s it! Now you can execute dotnet run command to start your gRPC service.

Enjoy!

Embed dependencies in your Assembly

Sometimes, when your assembly has many dependencies, you may have the need to simplify deployment. One useful approach is to embed dependent assembly into the main one. To proceed, you need to add the assembly as embedded resource into your project:

Add Embed Assembly

Then set the assembly as Embedded Resource:

Set Embedded Resource

Finally, the code is very simple. Subscribe to the AssemblyResolve event. That event is fired when the common language runtime is unable to locate and bind the requested assembly:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

Then, you must implement the event handler, read the assembly from resources and call the Assembly.Load method to load it:

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string assemblyName = args.Name.Split(',').First();
    string assemblyFolder = "Resources";
    string assemblyEmbeddedName = string.Format("{0}.{1}.{2}.dll",
        this.GetType().Namespace, assemblyFolder, assemblyName);

    Assembly currentAssembly = Assembly.GetExecutingAssembly();
    using (var stream = currentAssembly.GetManifestResourceStream(assemblyEmbeddedName))
    {
        if (stream == null)
        {
            return null;
        }

        var buffer = new byte[(int)stream.Length];
        stream.Read(buffer, 0, (int)stream.Length);
        return Assembly.Load(buffer);
    }
}

The above code assumes that the assembly are stored in a folder named Resources and the base namespace is the same of the current type.

Conclusion

At the end, we can analyze the pros and cons of this approach:

  • Pros
    • Reduced set of assemblies to deploy is the main reason that could suggest you to embed it in your assembly
  • Cons
    • Dependent assemblies needs to be manually updated when new release are available

This is a very simple way to read embedded assemblies. Be careful, use this approach only if it is really necessary.

Enjoy!

Implementing request-reply service in gRPC for .NET

With this post it’s time to get into the first service build with gRPC. First of all, we’ll use the dotnet command to create our solution:

gRPC Create New

When finished, in Visual Studio Code the project will look like this:

gRPC Project

We need to check the project and take a look into these items:

  1. The Services\*.cs files: contains the server-side implementation;
  2. The Protos\*.proto files: contains the Protocol Buffer file descriptors;
  3. The Startup.cs file: register the gRPC service by calling the MapGrpcService method;

Build our BookshelfService

Our first version of BookshelfService implements a simple method that allows saving a Book into our Bookshelf. To proceed, we need to change the default greet.proto by renaming to our brand new bookshelf.proto and changing its content with the following code:

syntax = "proto3";

option csharp_namespace = "BookshelfService";

package BookshelfService;

// The bookshelf service definition.
service BookService {
  // Save a Book
  rpc Save (NewBookRequest) returns (NewBookReply);
}

// The request message containing the book's title and description.
message NewBookRequest {
  string title = 1;
  string description = 2;
}

// The response message containing the book id.
message NewBookReply {
  string id = 1;
}

Now, we can open the GreeterService.cs and rename the class, and the file, into BookServiceImpl. Something like this:

namespace BookshelfService
{
    public class BookServiceImpl : BookService.BookServiceBase
    {
        private readonly ILogger<BookshelfServiceImpl> _logger;
        public BookshelfServiceImpl(ILogger<BookshelfServiceImpl> logger)
        {
            _logger = logger;
        }

        public override async Task<NewBookReply> Save(NewBookRequest request, ServerCallContext context)
        {
            // service implementation
        }
    }
}

Finally, be sure to change the MapGrpcService into your Startup.cs with this line:

endpoints.MapGrpcService<BookServiceImpl>();

Now, you’re ready to run your first gRPC service.

Wait, what happens? Let’s take a look under the hood

As previously said in this post the .proto file is responsible for the service definition. So, every time you change the .proto content, language-specific tools will generate the related objects. In our case, a set of C# classes. You can describe your service and the related messages by using a meta-language: the proto syntax.

As you can see, we have defined two messages (NewBookRequest and NewBookReply) and a service (BookService). The Protocol Buffer tool will generate the messages as .NET types and the service as an abstract base class. You’ll find the generated source file in the obj folder.

gRPC Obj Folder

Finally, to implements our service, we only need to extend the BookServiceBase class and overrides the defined methods. For example:

public override Task<NewBookReply> Save(NewBookRequest request, ServerCallContext context)
{
    var savedBook = BooksManager.SaveBook(request.Title, request.Description);
    return Task.FromResult(new NewBookReply
    {
        Id = savedBook.BookId
    });
}

Conclusion

This is a small example of a simple request/reply service integrated into an ASP.NET Core 3 application. You can test it by using BloomRPC or by creating a .NET client. We will see the second option in the next post.

Enjoy!

Test your .NET gRPC service

One of the most critical issue in the developer work is the test phase. If you want to test a SOAP service, SoapUI is one of the most well known tools. If you want to test a REST service, you can build your requests by using Fiddler or Postman. But, if you want to test a gRPC service, what you can use?

Searching for a tool, I found BloomRPC. Inspired by Postman and developed with Electron and React, it’s free and open source, works on Windows, Linux and MacOS, and, in my opinion, is one of the most simpler tool for testing gRPC.

The usage is really simple:

  1. add you .proto file to the project
  2. set the endpoint
  3. fill up your request with sample data
  4. press play button

BloomRPC example

In this example I’m runing and testing the Greeter server example from gRPC-dotnet.

You can download and check BloomRPC from GitHub: https://github.com/uw-labs/bloomrpc

Enjoy!

Disclaimer: I’m not affiliated, associated, authorized, endorsed by, or in any way officially connected with the BloomRPC project.

Using gRPC in x86 .NET applications

In this post we introduced gRPC and its .NET implementations. In some cases, you’ll need to use a gRPC client from a legacy Win32 process but, since the NuGet package of gRPC C# is based on the x64 C++ native library, it will not work as expected.

Luckly, a solution is really simple:

Before start to build, you need to build the C++ library. You can proceed in two ways:

  • follow the steps on building page
  • be sure that you have the x86 version of grpc_csharp_ext.dll in cmake\build\x86\Release (or Debug) folder

To get the libraries, create a new project and add a nuget reference to Grpc package. Then go to packages\Grpc.Core.2.24.0\runtimes\win\native and copy the grpc_csharp_ext.x86.dll library in the previously mentioned cmake\build\x86\Release folder. Finally, be sure to rename the library in grpc_csharp_ext.dll. Now you’ll be able to build from Visual Studio 2019.

Enjoy!

Speed up your .NET microservice with gRPC

For those who still don’t know, gRPC is a RPC (Remote Procedure Call) framework with high performance in mind. Born in Google and used for years, it has been recently released to the open source world and now is supported in about 10 specific languages: from C# to Java, C++ or Go.

In this post we’ll made a really basic overview focusing on the basic concepts of gRPC and its main characteristics.

On my way to gRPC

RPC is not a new concept. We’ve started speaking about RPC in the late sixties but the first real implementation comes in the early 80s. It become very popular only in the nineties with Java Remote Method Invocation. In the following years we try to manage RPC in many ways: CORBA, .NET Remoting and WCF are just some example of this attempt.

But, why gRPC? Well, in the last few years, new scenarios comes - think about the increased number of connection from mobile device - and we need to adapt software architecture to responde to this new requirements: interoperability, openness, scalability, performance. gRPC was created with exactly these characteristics in mind and is based on two different technology: HTTP/2 and Protobuf.

HTTP/2 stream

HTTP/2 represents the evolution of the most famous HTTP/1.1 protocol, providing the best way to transport data by supporting binary and an optimized connection usage (single connection vs multiple connection). You can read the HTTP/2 RFC 7540 or get a short description here. The transmitted binary data, when using gRPC, is represented by the use of Protobuf.

Protobuf is a “Google’s mature open source mechanism for serializing structured data”. So, what does this mean? One of the big problem with REST is that you don’t have something like a WSDL doc that describes the service and helps you build a client, but you need documentation or samples before you can do it. With Protobuf you can write the service and data structure in a metalanguage and, later, you can use specific-language generator to build your own client and server side code.

Take this example:

message RequestMessage
{
  string FirstName = 1;
  string LastName = 2;
}

message ResponseMessage
{
  string FullName = 1;
}

service NameService
{
  rpc GetFullName (RequestMessage) returns (ResponseMessage) {}
}

You can build any supported language-specific code starting from this .proto file, so you can simply share that file with any client that needs to interact with your service. Wonderful!

gRPC in .NET

You can write services and clients in C# with gRPC by using two different libraries:

  • gRPC C#: implementation based on Core native library https://www.nuget.org/packages/Grpc
  • gRPC for .NET: managed implementation

The first one supports .NET Framework 4.5 and .NET Standard 1.5/2.0 while the second one supports .NET Standard 2.1 so you can use it only with .NET Core 3.0.

In the next posts we’ll explore the two implementations, checking the difference and how you can use it. In the meantime, on the official gRPC site, you can find guides and tutorials to start using the brand new microservice framework.

Enjoy!

Blazor now in official preview

Some days ago, the ASP.NET team announce the official preview of Blazor, the Microsoft framework for building Single Page Application. Note that in the post, they declare that Server-Side Blazor will ship as part of .NET Core 3.0, announced for second half 2019, while Client-side Blazor will ship as part of a future .NET Core release.

Upgrade to Blazor preview

To upgrade your existing Blazor apps to the new Blazor preview first make sure you’ve installed the prerequisites listed above then follow these steps:

  • Update all Microsoft.AspNetCore.Blazor.* package references to 3.0.0-preview4-19216-03 by changing the PackageReference in csproj with this: <PackageReference Include="Microsoft.AspNetCore.Blazor" Version="3.0.0-preview4-19216-03" />
  • Remove any package reference to Microsoft.AspNetCore.Components.Server
  • Remove any DotNetCliToolReference to Microsoft.AspNetCore.Blazor.Cli and replace with a package reference to Microsoft.AspNetCore.Blazor.DevServer
  • In client Blazor projects remove the <RunCommand>dotnet</RunCommand> and <RunArguments>blazor serve</RunArguments> properties
  • In client Blazor projects add the <RazorLangVersion>3.0</RazorLangVersion> property
  • Rename all _ViewImports.cshtml files to _Imports.razor
  • Rename all remaining .cshtml files to .razor
  • Rename components.webassembly.js to blazor.webassembly.js
  • Remove any use of the Microsoft.AspNetCore.Components.Services namespace and replace with Microsoft.AspNetCore.Components as required.
  • Update server projects to use endpoint routing:

Replace this:

app.UseMvc(routes =>
{
    routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}");
});

With this:

app.UseRouting();

app.UseEndpoints(routes =>
{
    routes.MapDefaultControllerRoute();
});

Run dotnet clean on the solution to clear out old Razor declarations.

https://devblogs.microsoft.com/aspnet/blazor-now-in-official-preview/

Enjoy!

Goodbye TLScrollView. Welcome BindableLayout!

Three years ago I wrote a blog post about my Xamarin.Forms component TLScrollView, a simple horizontal scrollview with bindable feature. The post was one of the most viewed and commented, and I’m really happy about that, but now, with the latest version of Xamarin.Forms, you can use the new BindableLayout feature.

Move TLScrollView to BindableLayout

Looking back, in my post you can see how to use the TLScrollView control:

<controls:TLScrollView Orientation="Horizontal" ItemsSource="{Binding Items}" HeightRequest="100">
    <controls:TLScrollView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Padding="5">
                    <controls:TLImageCircle Source="{Binding Image}" HeightRequest="80" WidthRequest="80" />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </controls:TLScrollView.ItemTemplate>
</controls:TLScrollView>

Change the code to support the BindableLayout is really simple. You don’t need to use my custom control since the BindableLayout is applicable to all Layout Xamarin.Forms controls. So, using the StackLayout, add the BindableLayout.ItemsSource attribute and the BindableLayout.ItemTemplate attribute to implement the binding. Here you can see the new code:

<StackLayout Orientation="Horizontal" BindableLayout.ItemsSource="{Binding Items}" HeightRequest="100">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Padding="5">
                    <controls:TLImageCircle Source="{Binding Image}" HeightRequest="80" WidthRequest="80" />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

Check here how the BindableLayout works.

Enjoy!