Hands-On Exercise: Calling a Custom gRPC Method from Blazor Server

Hands-On Exercise: Calling a Custom gRPC Method from Blazor Server

Hands-On Exercise: Calling a Custom gRPC Method from Blazor Server

This exercise walks you through a common scenario: building a user dashboard where a Blazor Server application needs to fetch user details from a gRPC service by sending a user ID. This guide will cover creating the gRPC service, implementing its logic, consuming it from the Blazor app, and displaying the result on the UI.


Step 1: Define the gRPC Contract with .proto File

First, we'll define the service and message types in our gRPC contract.

1.1 Create `hello.proto` File

Create a file named `hello.proto` in your gRPC server project at `GrpcDemo.Server/Protos/hello.proto`.


syntax = "proto3";

option csharp_namespace = "GrpcDemo";
package user;

service UserService {
  rpc GetUserDetails (UserRequest) returns (UserResponse);
}

message UserRequest {
  int32 user_id = 1;
}

message UserResponse {
  int32 user_id = 1;
  string name = 2;
  int32 age = 3;
  string city = 4;
}
        

**Explanation:**

  • `syntax = "proto3"`: Specifies the version of Protocol Buffers.
  • `option csharp_namespace`: Instructs the Protobuf compiler to generate C# classes in the `GrpcDemo` namespace.
  • `package user`: Organizes the generated code under a logical package, which will become a namespace prefix in C#.
  • `UserService`: Defines our RPC service with a single method, `GetUserDetails`, which takes a `UserRequest` and returns a `UserResponse`.

1.2 Add `.proto` Reference to gRPC Server Project

Edit your `GrpcDemo.Server.csproj` file to tell the build process to compile the `.proto` file and generate the necessary server-side C# code.


<ItemGroup>
  <Protobuf Include="Protos\hello.proto" GrpcServices="Server" />
</ItemGroup>
        

Step 2: Implement the gRPC Service on the Server

Now we'll write the code that will actually handle the gRPC call.

2.1 Create `UserService.cs` in `GrpcDemo.Server/Services`

This class will inherit from the generated base class and contain the logic for fetching user details.


using Grpc.Core;
using user;

public class UserService : user.UserService.UserServiceBase
{
    private readonly Dictionary<int, (string Name, int Age, string City)> _users = new()
    {
        { 1, ("Alice", 28, "Delhi") },
        { 2, ("Bob", 32, "Mumbai") },
        { 3, ("Charlie", 25, "Bangalore") }
    };

    public override Task<UserResponse> GetUserDetails(UserRequest request, ServerCallContext context)
    {
        if (_users.TryGetValue(request.UserId, out var data))
        {
            return Task.FromResult(new UserResponse
            {
                UserId = request.UserId,
                Name = data.Name,
                Age = data.Age,
                City = data.City
            });
        }
        throw new RpcException(new Status(StatusCode.NotFound, "User not found"));
    }
}
        

2.2 Register Service in `Program.cs`

Finally, register the `UserService` so the server knows how to handle incoming gRPC requests for this service.


app.MapGrpcService<UserService>();
        

Make sure to place this after `app.UseRouting()` but before `app.Run()`.


Step 3: Setup the Blazor Server Project

Now we'll configure the client-side project to be able to talk to our server.

3.1 Copy `hello.proto` to Blazor Project

As we discussed in the last post, both the client and server need the same `.proto` file. Copy `hello.proto` to `GrpcDemo.Blazor/Protos/hello.proto`.

3.2 Reference the .proto in Blazor Project File

Edit your `GrpcDemo.Blazor.csproj` to generate client-side stubs.


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

This time, the `GrpcServices` attribute is set to `Client`.

3.3 Add Required NuGet Packages

Ensure you have the necessary NuGet packages installed in your Blazor project.


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

Step 4: Register gRPC Client in Blazor

In `GrpcDemo.Blazor/Program.cs`, we need to register the gRPC client with the dependency injection container.


builder.Services.AddGrpcClient<user.UserService.UserServiceClient>(o =>
{
    o.Address = new Uri("https://localhost:5001");
});
        

This makes the `UserServiceClient` available for injection into our Razor components.


Step 5: Create Razor Page to Call gRPC

Finally, we'll create a simple UI to interact with our gRPC service.

5.1 Add New Razor Component: `Pages/UserLookup.razor`

This page will contain a form to input a user ID and display the results.


@page "/user-lookup"
@inject user.UserService.UserServiceClient UserClient

<h3>User Lookup</h3>

<input @bind="userId" type="number" placeholder="Enter User ID" />
<button @onclick="FetchUser">Fetch User</button>

@if (error != null)
{
    <p style="color:red">@error</p>
}
else if (user != null)
{
    <div>
        <p><b>Name:</b> @user.Name</p>
        <p><b>Age:</b> @user.Age</p>
        <p><b>City:</b> @user.City</p>
    </div>
}

@code {
    int userId;
    user.UserResponse? user;
    string? error;

    async Task FetchUser()
    {
        try
        {
            var response = await UserClient.GetUserDetailsAsync(new user.UserRequest { UserId = userId });
            user = response;
            error = null;
        }
        catch (Grpc.Core.RpcException ex)
        {
            error = ex.Status.Detail;
            user = null;
        }
    }
}
        

The code block shows how to inject the gRPC client, create a method to make the call, and use a `try-catch` block to handle potential errors like a user not being found.

5.2 Add Link in `NavMenu.razor`

Update your `Shared/NavMenu.razor` file to add a navigation link to our new page.


<li class="nav-item px-3">
    <NavLink class="nav-link" href="user-lookup" Match="NavLinkMatch.All">
        <span class="oi oi-person" aria-hidden="true"></span> User Lookup
    </NavLink>
</li>
        

Final Project Structure Recap

For clarity, here is how the final project structure should look.


GrpcDemo/
├── GrpcDemo.Server/
│   ├── Protos/hello.proto
│   ├── Services/UserService.cs
│   └── Program.cs
├── GrpcDemo.Blazor/
│   ├── Protos/hello.proto
│   ├── Pages/UserLookup.razor
│   └── Program.cs
        

Test It Out

1. Run both the `GrpcDemo.Server` and `GrpcDemo.Blazor` projects. 2. Open your browser and navigate to the Blazor app. 3. Use the "User Lookup" link to go to the new page. 4. Try entering user IDs `1`, `2`, or `3` to see the user details. 5. Try entering a non-existent ID like `99` to see the "User not found" error.

This exercise demonstrates the full flow of defining, implementing, and consuming a custom gRPC method in a real-world scenario.

Raushan Ranjan

Microsoft Certified Trainer

.NET | Azure | Power Platform | WPF | Qt/QML Developer

Power BI Developer | Data Analyst

📞 +91 82858 62455
🌐 raushanranjan.azurewebsites.net
🔗 linkedin.com/in/raushanranjan

Comments

Popular posts from this blog

Blazor: Building Web Apps with C# - Introduction

Blazor WebAssembly Hosted App Tutorial: Envelope Tracker System

Securing MVC-based Applications Using Blazor