Click here to Skip to main content
15,890,897 members
Articles / Programming Languages / C#

C#/.NET gRPC Service with Unary Methods

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
20 Feb 2024CPOL3 min read 2.9K  
Implement unary methods on a gRPC service using C#/.NET
This is a tutorial on how to implement and test unary methods on a gRPC service using C#/.NET.

Introduction

gRPC is a modern, open source, high performance RPC (remote-procedure-call) framework. It runs on all platforms (Windows, Mac and Linux) and is supported on all major programming languages. As with all RPC programming models, it hides away the networking aspect of the call and makes it appear as if it is a normal, in-process function call.

Due to the performance benefits of gRPC over HTTP-based REST APIs, it is widely used in scenarios where performance is a high priority, such as when processing high data loads, or when there is a need for real-time data streaming. A common architecture adopted by various organizations is to have a public-facing HTTP/REST API (for maximum interoperability) that is backed internally by gRPC microservices (for maximum performance).

Service Definitions and Protobuf

Similar to WCF (Windows Communication Foundation), gRPC relies on service definitions to specify what methods and data types are exposed by the service. Service definitions in gRPC are written in protocol buffers (or protobuf for short) whereas in WCF, a WSDL is used.

An example of a protobuf service definition is shown below. It defines a service named HelloService which has a single method called SayHello. SayHello accepts a request parameter of type HelloRequest and returns a response of type HelloResponse.

protobuf
service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

Unary Methods

Unary methods are rpc (remote-procedure-call) calls wherein for every request, a response is sent back. It’s a lot similar to the normal function calls that we all write in our code except that for gRPC, the calls go over the network. In the above service definition, SayHello is a unary method.

Implementation (Server)

To create a gRPC project, fire up Visual Studio and run the project template ASP.NET Core gRPC Service. By default, dotnet creates a greet.proto file which contains the service definition of the generated GreeterService class. The content of this greet.proto file is similar to the service definition a few paragraphs above.

Let’s create a second Unary method called GetCustomerByName by editing the greet.proto file:

protobuf
syntax = "proto3";

option csharp_namespace = "GrpcUnary";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
  rpc GetCustomerByName (GetCustomerRequest) returns (GetCustomerResponse);
}

// The request message containing the user's name.
message GetCustomerRequest {
  string namePrefix = 1;
}

// The response message containing the greetings.
message GetCustomerResponse {
  repeated Customer customer = 1;
}

message Customer {
    string firstName = 1;
    string lastName = 2;
    int32 age = 3;
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

Press Ctrl-Shift-B to build the solution. If there are no errors in the proto file, the build should be successful.

Now that we have modified the service definition to include the GetCustomerByName method, we can go ahead and implement it in code. Open up GreeterService.cs and add an override for the method. Let's simulate a call to a Customers DB and - when a record is not found, we'll throw an RPC exception with a status code of NotFound.

C#
public override async Task<GetCustomerResponse> GetCustomerByName
                (GetCustomerRequest request, ServerCallContext context)
{
    //Simulate a Db call to the Customers database
    var matched = _customers.Where(c => c.FirstName.StartsWith(request.NamePrefix));
    if (matched.Any())
    {
        var response = new GetCustomerResponse();
        response.Customers.AddRange(matched);
        return response;
    }

    throw new RpcException(new Status(StatusCode.NotFound, 
     $"Unable to find a customer with a first name starting with {request.NamePrefix}"));
}

Press F5 to run the service and take note of the port where it is running.

Test the Method

Now that the service is running, let’s fire up FintX (https://github.com/namigop/FintX) to verify that the service is working fine. FintX is an open-source, native, and cross-platform gRPC client. I’m on Windows, so I have installed the windows package (macOS and Linux downloads are also available).

Click on the plus icon to add a client. The value entered in the http address should match the running service.

Open GetCustomerByName method and edit the request. Double-click on the NamePrefix node to edit it, then click the Run button.

Give the NamePrefix some invalid value to verify that indeed an RPC exception is thrown with a NotFound status code.

Conclusion

In this tutorial post, you've seen how to implement and test unary methods in a gRPC service. They are quite easy and straightforward to implement.

History

  • 20th February, 2024: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Singapore Singapore
Erik eats and breathes 1's and 0's

Comments and Discussions

 
-- There are no messages in this forum --