gRPC Channel throws null reference exception in Blazor client

Viewed 89

I've a gRPC service written in .NET 6 that is running fine on localhost. I'm trying to consume it in a Blazor client for .NET 6. but, I'm getting System.NullReferenceException when creating that channel for my gRPC service.

SERVICE HELPER

public class ServiceHelper : IServiceHelper
{
    public Server.ServerClient? ServerClient { get; set; }
    public ServiceHelper()
    {
        try
        {
            GrpcChannel channel = GrpcChannel.ForAddress("https://localhost:7027");
            ServerClient = new Server.ServerClient(channel);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
}  

Program.cs for Client

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddAntDesign();

//var serviceAddress = builder.Configuration["ServiceAddress"];

builder.Services.AddSingleton<IServiceHelper, ServiceHelper>();

await builder.Build().RunAsync();  

Using the gRPC Client

@inject IServiceHelper _serviceHelper

<div class="page elementFillSpaceY">
  
</div>

@code
{
    public ServerStatus? ServerStatus { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await SetUpData();
    }

    private async Task SetUpData()
    {
        var client = _serviceHelper.ServerClient;

        if (client != null)
        {
            var result = await client.GetServerStatusAsync(new Empty());
            ServerStatus = result;
            Debug.WriteLine(ServerStatus.Status);
        }
    }

}  

Program.cs for gRPC Service

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddGrpc();
const string corsPolicy = "_corsPolicy";
/*builder.Services.AddCors(options =>
{
    options.AddPolicy(name: corsPolicy,
        policy =>
        {
            /*policy.WithOrigins("https://localhost:7075",
                    "http://localhost:5025")
            policy.AllowAnyOrigin()
                .WithExposedHeaders("grpc-status", "grpc-message")
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
});*/

var app = builder.Build();
//app.UseCors(corsPolicy);
//app.UseRouting();
//app.UseGrpcWeb();
// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();
app.MapGrpcService<ServerService>();
app.MapGet("/",
    () =>
        "Communication with gRPC endpoints must be made through a gRPC client.");


app.Run();  

I've tried different ways of consuming gRPC service in client e.g. Dependency Injection for Channel and on gRPC side look at the commented code that i have tried but still getting same error. It just throws the null reference exception without any other detail.

Exception Image

Stack trace of exception

'at Grpc.Net.Client.Balancer.Internal.BalancerHttpHandler..ctor(HttpMessageHandler innerHandler, HttpHandlerType httpHandlerType, ConnectionManager manager)\n at Grpc.Net.Client.GrpcChannel.CreateInternalHttpInvoker(HttpMessageHandler handler)\n at Grpc.Net.Client.GrpcChannel..ctor(Uri address, GrpcChannelOptions channelOptions)\n at Grpc.Net.Client.GrpcChannel.ForAddress(Uri address, GrpcChannelOptions channelOptions)\n at Grpc.Net.Client.GrpcChannel.ForAddress(String address, GrpcChannelOptions channelOptions)\n at Grpc.Net.Client.GrpcChannel.ForAddress(String address)\n at BusinessBlazor.Helpers.ServiceHelper..ctor() in ....'

1 Answers

I am not exactly sure why the exception is thrown. But, with a pretty high probability, it may be thrown because the GrpcChannel.ForAddress can not construct a valid HttpClient for the communication. Possible steps to debug and fix this issue

  1. Ensure that your server is actually up and accessible via the URL https://localhost:7027
  2. Try to construct and pass the HttpClient explicitly. See example here. Also, note that in the client service you registered the HttpClient as Scoped, so you won't be able to fetch it from DI container in the Singleton service.
  3. Try to add the gRPC client via builder.Services.AddGrpcClient and get it from the DI. Example here

I really hope that it will help to solve your problem. Good luck!

Related