With these two changes, we are set for developing our services in the following steps
When we have added ToDo.Proto file we will have the following structure like below
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.
Message Payload will define the data structure which will be passed to and from the service here we have the service definitions.
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.
Code Explanation
Here we are adding a class ToDoDataService.cs which is getting inherited from the ToDoService.ToDoServiceBase class which is nothing but the stub generated from our proto file which will have the definition of the services which we have defined in the Proto file. Next we have implemented all the methods in the Proto file which will perform the basic operations which we perform normally.
Startup Changes
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.AspNetCore.Http;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using ToDoGrpcService.Services;
-
- namespace ToDoGrpcService
- {
- public class Startup
- {
-
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddGrpc();
- services.AddDbContext<ToDoDataContext>(options =>options.UseInMemoryDatabase("ToDoDatabase"));
-
- }
-
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env,ToDoDataContext ctx)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- new ToDoGenerator(ctx).ToDoDataSeed();
-
- app.UseRouting();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapGrpcService<GreeterService>();
- endpoints.MapGrpcService<ToDoDataService>();
-
- endpoints.MapGet("/", async context =>
- {
- await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
- });
- });
- }
- }
- }
Here a couple of changes are needed to get our service up and running. Map the endpoints to the gRPC service. In the first method, ConfigureServices, we are adding the gRPC Services in the collection and for our demo purpose we are using InMemoryDatabase so we are configuring the DbContext to use the InMemory Database
The next set of Changes is needed at the Configure Method where we will do Some Database seeding which will add the initial items in the database. The next change is at the map endpoints to the gRPC service. Here we are mapping the gRPC service implementation ToDoDataService to the endpoints.
Now we have implemented the Service. Let's try to implement the Client app which will be our Blazor server-side app. In the first project section we have added one Blazor project now let’s see the basic components which will operate for us. Follow the below step to get our app working
Initial setup and Nuget packages
Once we are done with adding a project we need to add some NuGet packages which will help in implementing the clients for the gRPC Nuget Package which will be needed will be like below,
- Google.ProtoBuff
- Grpc.Net.Client
- Grpc.Tools
Once we are done with the packages let's configure our client to compile and include the proto files
Adding Proto File and Configure gRPC Client
gRPC Clients are nothing but concrete types which are generated from the Proto files to generate the gRPC Client. Let's add our proto files in the Project; for that let us make a folder Called Proto.
Once they are added in the Project let's change and configure the Proto files to be compiled as a Client. In the service section we have made them be compiled as a service so let's modify our .csproj file and make them a client like below.
- <ItemGroup>
- <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
- <Protobuf Include="Protos\ToDo.proto" GrpcServices="Client" />
- </ItemGroup>
In this Section we have modified and made sure we are compiling our proto files as a client. How we can implement the client? Let's see while developing the services.
Add New Razor Component
Right-click on project -> Add New Item ->> Add New Razor Component. Name it ToDoOperation.razor like the image below.
Code for the Razor Component will be like below
Add Component Class
Here in our code-behind code, we have injected a service ToDoDataService which will hold all our gRPC operations.
Design Service to Call gRPC Methods
Code for the ToDoData Service will be like below.
- using Grpc.Net.Client;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
-
- namespace BlazorClient.Services
- {
- public class ToDoDataService
- {
-
-
- private ToDoGrpcService.ToDoService.ToDoServiceClient GetServiceClient()
- {
- var channel = GrpcChannel.ForAddress("https://localhost:5001");
- return new ToDoGrpcService.ToDoService.ToDoServiceClient(channel);
- }
-
- public bool AddToDoData(Data.ToDoDataItem toDoDataItem)
- {
-
- var client = GetServiceClient();
-
- var todoData = new ToDoGrpcService.ToDoData()
- {
- Status = toDoDataItem.Status,
- Title = toDoDataItem.Title,
- Description = toDoDataItem.Description
- };
-
- var response = client.PostToDoItem(todoData, null);
- return response.Status;
-
- }
- public bool UpdateToDoData(Data.ToDoDataItem toDoDataItem)
- {
- var client = GetServiceClient();
- var updateData = new ToDoGrpcService.ToDoPutQuery();
- updateData.Id = toDoDataItem.Id;
- updateData.ToDoDataItem = new ToDoGrpcService.ToDoData()
- {
- Id = toDoDataItem.Id,
- Status = toDoDataItem.Status,
- Title = toDoDataItem.Title,
- Description = toDoDataItem.Description
- };
- var response = client.PutToDoItem(updateData, null);
- return response.Status;
- }
- public bool DeleteData(string ToDoId)
- {
- var client = GetServiceClient();
- var response = client.DeleteItem(new ToDoGrpcService.ToDoQuery() { Id = Convert.ToInt32(ToDoId) }, null);
- return response.Status;
- }
- public ToDoGrpcService.ToDoItems GetToDoList()
- {
- var client = GetServiceClient();
- return client.GetToDo(new Google.Protobuf.WellKnownTypes.Empty(), null);
-
- }
-
- public Data.ToDoDataItem GetToDoItem(int id)
- {
- var client = GetServiceClient();
- var todoItem = client.GetToDoItem(new ToDoGrpcService.ToDoQuery() { Id = Convert.ToInt32(id) }, null);
-
- return new Data.ToDoDataItem() { Title = todoItem.Title, Description = todoItem.Description, Status = todoItem.Status, Id = todoItem.Id };
-
- }
- }
- }
Here as you can see we have added all our methods like Add, Update, Delete Get Methods which will call their operations accordingly. Here we are creating the gRPC Client and that will be used to call all the operations.
Add Service in the Service Collection
To make sure service is available in the application let's add the service in the collection with a single line like below.
- services.AddSingleton<BlazorClient.Services.ToDoData
Once we have all this implemented we will have an output like below,
Source code
You can find all this source code here
Source code