How to inject a service into Blazor?

1.7k Views Asked by At

I'm having trouble trying to inject some services into the client project. In the Program.cs file I have the following:

public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

            await builder.Build().RunAsync();

            ConfigureServices(builder.Services);

        }


        public static void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IMetamaskInterop, MetamaskBlazorInterop>();
            services.AddSingleton<MetamaskService>();
            services.AddSingleton<MetamaskInterceptor>();
        }
    }

In a new component I try to inject these services as follows:

@inject IJSRuntime JSRuntime;
@inject MetamaskService metamaskService;
@inject MetamaskInterceptor metamaskInterceptor;

But doing this is giving me an error and it is the following:

enter image description here

I appreciate any help or guidance.

2

There are 2 best solutions below

0
On BEST ANSWER

You shouldn't introduce a new static method named ConfigureServices into the Program class. This is not the reason for the exception thrown, but it is greatly misleading as ConfigureServices is the name of a method defined in the Startup class (used in the past in WebAssembly Blazor, and then removed...).

Sometimes, you may need a second method for conditional configuration, but don't name it ConfigureServices. In the current instance, you don't need a second method. Just do it as it is done below.

When you use a second method, you mustn't run await builder.Build().RunAsync(); as this code build and execute your app, rendering it too late to add more services to the service collection. Just pass the IServiceCollection object to the second method, and when it returns build and run your app.

Here's the updated version of your code:

public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            
            builder.Services.AddSingleton<IMetamaskInterop, MetamaskBlazorInterop>();
            builder.Services.AddSingleton<MetamaskService>();
            builder.Services.AddSingleton<MetamaskInterceptor>();

            await builder.Build().RunAsync();
        }
    }  
0
On

You are configuring the services after you start you app.

Add ConfigureServices(builder.Services); before await builder.Build().RunAsync();.

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");

        builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

        // configure services before running the app
        ConfigureServices(builder.Services);

        await builder.Build().RunAsync();

    }


    public static void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IMetamaskInterop, MetamaskBlazorInterop>();
        services.AddSingleton<MetamaskService>();
        services.AddSingleton<MetamaskInterceptor>();
    }
}