Agenda
- Introduction
- Project setup
- Implementing gRPC Service
- Implementing Blazor App
- Integrating the Blazor and gRPC Service
- Source Code
Introduction
gRPC has become the main talking point recently after the launch of the .Net core 3.0. This article will demonstrate one ToDo Blazor app which will be integrated to the gRPC service and perform the basic CRUD operation. If you are new to the gRPC and its terminologies just go through my previous articles.
Project setup
To get the gRPC Service as well as Blazor server up and running we need basic installation of two things
- .Net Core SDK 3.0 or Later
- Visual studio 2019
Now there are two types of projects we are going to add here first is the gRPC Project and another will be the gRPC service project.
Adding gRPC Service

Adding Blazor App
Here Open Add New Project wizard and select the Blazor App which will be the server-side Blazor App like in the image below.
Implementing gRPC Service
We have seen how we have set up the gRPC service project and then the client-side blazor app now in this section let's implement the service and the basic CRUD operation with it. As we all know gRPC uses ProtoBuff ( Protocol Buffers ) as an Interface Definition language for defining services and structure of the payload message.
In our case, we are going to implement the ToDo app which will perform all basic ToDo CRUD operations. The first step in implementing the gRPC service is to implement the protobuff file lets see step by step how we can manipulate the ProtoBuff file
Add New ProtoBuff File
To add new Proto file Right-click on the ToDoGrpc Service Project it will open add new Item wizard lets search for protocol buffer option

Before compiling this we need to make sure are we open the .csProj file of your project and make the following changes once so that our proto file will be compiled and it will generate the stub accordingly
- <ItemGroup>
- <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
- <Protobuf Include="Protos\ToDo.proto" GrpcServices="Server" />
- <Protobuf Include="Protos\Sample.proto" GrpcServices="Server" />
- </ItemGroup>
Defining Protocol Format
When we have added ToDo.Proto file we will have the following structure like below
- syntax = "proto3";
- option csharp_namespace = "ToDoGrpcService";
- import "google/protobuf/empty.proto";
- package ToDo;
- service ToDoService{
- rpc GetToDo(google.protobuf.Empty) returns (ToDoItems);
- rpc GetToDoItem(ToDoQuery) returns (ToDoData );
- rpc PostToDoItem(ToDoData) returns(ToDoPostResponse);
- rpc PutToDoItem(ToDoPutQuery) returns(ToDoPostResponse);
- rpc DeleteItem(ToDoQuery) returns (ToDoPostResponse);
- }
- message ToDoData{
- int32 Id=4;
- string Title=1;
- string Description=2;
- bool Status=3;
- }
- message ToDoQuery{
- int32 id=1;
- }
- message ToDoItems{
- repeated ToDoData ToDoItemList =1;
- }
- message ToDoPutQuery{
- ToDoData ToDoDataItem=1;
- int32 Id=2;
- }
- message ToDoPostResponse{
- string StatusMessage=1;
- bool Status=2;
- int32 StatusCode=3;
- }
Package Declaration
- syntax = "proto3";
- option csharp_namespace = "ToDoGrpcService";
- import "google/protobuf/empty.proto";
- package ToDo;
Here we have to do some initial setup and import some packages. In the first line we are specifying the proto3 as a syntax for the proto file. Next is the CSharp namespace which will be the default namespace for the stub which will be generated. Next is the import section where we will be importing the empty.proto file which we are going to use in the next section.
Defining the Message Payload
- message ToDoData{
- int32 Id=4;
- string Title=1;
- string Description=2;
- bool Status=3;
- }
- message ToDoQuery{
- int32 id=1;
- }
- message ToDoItems{
- repeated ToDoData ToDoItemList =1;
- }
- message ToDoPutQuery{
- ToDoData ToDoDataItem=1;
- int32 Id=2;
- }
- message ToDoPostResponse{
- string StatusMessage=1;
- bool Status=2;
- int32 StatusCode=3;
- }
Code Explanation
|
Message Name
|
Fields
|
Description
|
|
ToDoData
|
Id,
Title
Description,
Status
|
This is the basic format for the ToDo list where Id , Title Description and status will be held.
|
|
ToDoQuery
|
id
|
This data structure will be used while querying the ToDo Item
|
|
ToDoItems
|
Repeated ToDoData
|
This will be a list of the ToDo Data Items
|
|
ToDoPutQuery
|
ToDoData ToDoDataItem
Id
|
This will be used in updating the ToDo Record where Id will hold the Id of the ToDo Item
|
|
ToDoPostResponse
|
StatusMessage,
Status,
StatusCode
|
This will be the Data which will be returned after All POST Operations.
|
Service Declaration
- service ToDoService{
- rpc GetToDo(google.protobuf.Empty) returns (ToDoItems);
- rpc GetToDoItem(ToDoQuery) returns (ToDoData );
- rpc PostToDoItem(ToDoData) returns(ToDoPostResponse);
- rpc PutToDoItem(ToDoPutQuery) returns(ToDoPostResponse);
- rpc DeleteItem(ToDoQuery) returns (ToDoPostResponse);
- }
Message Payload will define the data structure which will be passed to and from the service here we have the service definitions.
|
Service Name
|
Params
|
Returns
|
Description
|
|
GetToDo
|
Google.Protobuff.Empty
|
ToDoItems
|
It gets all the To Do Items from the database
|
|
GetToDoItem
|
ToDoQuery
|
ToDoData
|
It will give the Item based on the Id which is passed in the Query
|
|
PostToDoItem
|
ToDoData
|
ToDoPostResponse
|
This service will create new ToDo Item in Db
|
|
PutToDoItem
|
ToDoPutQery
|
ToDoPostResponse
|
It will update the Existing ToDo Item
|
|
DeleteItem
|
ToDoQuery
|
ToDoPostResponse
|
Deletes the ToDoItem
|
So far we have defined the services and messages. Now when these proto files are compiled successfully it will generate some stub which will be the base for the service implementation.
Service Implementations
Below is the code which will implement the actual service
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Google.Protobuf.WellKnownTypes;
- using Grpc.Core;
- namespace ToDoGrpcService.Services
- {
- public class ToDoDataService : ToDoService.ToDoServiceBase
- {
- private readonly ToDoDataContext _dataContext;
- public ToDoDataService(ToDoDataContext dataContext)
- {
- _dataContext = dataContext;
- }
- /// <summary>
- /// Get All Data
- /// </summary>
- /// <param name="request"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- public override Task<ToDoItems> GetToDo(Empty request, ServerCallContext context)
- {
- ToDoItems objItems = new ToDoItems();
- foreach (var item in _dataContext.ToDoDbItems)
- {
- objItems.ToDoItemList.Add(item);
- }
- return Task.FromResult(objItems);
- }
- /// <summary>
- /// Post Data
- /// </summary>
- /// <param name="request"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- public override Task<ToDoPostResponse> PostToDoItem(ToDoData request, ServerCallContext context)
- {
- _dataContext.ToDoDbItems.Add(request);
- var result = _dataContext.SaveChanges();
- if (result>0)
- {
- return Task.FromResult(new ToDoPostResponse()
- {
- Status = true,
- StatusCode = 100,
- StatusMessage = "Added Successfully"
- });
- }
- else
- {
- return Task.FromResult(new ToDoPostResponse()
- {
- Status = false,
- StatusCode = 500,
- StatusMessage = "Issue Occured."
- });
- }
- }
- /// <summary>
- /// Get Item with the Id
- /// </summary>
- /// <param name="request"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- public override Task<ToDoData> GetToDoItem(ToDoQuery request, ServerCallContext context)
- {
- var result = from data in _dataContext.ToDoDbItems
- where data.Id == request.Id
- select data;
- return Task.FromResult(result.First());
- }
- /// <summary>
- /// Deletes the Item
- /// </summary>
- /// <param name="request"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- public override Task<ToDoPostResponse> DeleteItem(ToDoQuery request, ServerCallContext context)
- {
- var item = (from data in _dataContext.ToDoDbItems
- where data.Id == request.Id
- select data).Single();
- _dataContext.ToDoDbItems.Remove(item);
- var result = _dataContext.SaveChanges();
- if (result > 0)
- {
- return Task.FromResult(new ToDoPostResponse()
- {
- Status = true,
- StatusCode = 100,
- StatusMessage = "Deleted Successfully"
- });
- }
- else
- {
- return Task.FromResult(new ToDoPostResponse()
- {
- Status = false,
- StatusCode = 500,
- StatusMessage = "Issue Occured."
- });
- }
- }
- /// <summary>
- /// Updates the item
- /// </summary>
- /// <param name="request"></param>
- /// <param name="context"></param>
- /// <returns></returns>
- public override Task<ToDoPostResponse> PutToDoItem(ToDoPutQuery request, ServerCallContext context)
- {
- _dataContext.ToDoDbItems.Update(request.ToDoDataItem);
- var result = _dataContext.SaveChanges();
- if (result > 0)
- {
- return Task.FromResult(new ToDoPostResponse()
- {
- Status = true,
- StatusCode = 100,
- StatusMessage = "Updated Successfully "
- });
- }
- else
- {
- return Task.FromResult(new ToDoPostResponse()
- {
- Status = false,
- StatusCode = 500,
- StatusMessage = "Issue Occured."
- });
- }
- }
- }
- }



Karim SaikaliPosted May 21, 2020, 5:37 AM
Great articles! The way you present and documented your articles is just great! Keep doing you are helping a lot of other programmers!
Sourav Kumar DasPosted Jan 2, 2020, 10:28 PM
Nice and useful article.
Ankur MistryPosted Jan 2, 2020, 8:37 PM
Excellent work keep it up