Blazor framework like other frameworks (Angular, etc.) offers support for Dependency Injection(DI). You can use the built-in services by injecting them into components. You can also create custom services, register and use them like any other service. Today you will learn how to use the built-in services and we will also create our own custom one that we will use in our application.

What Dependency Injection is? 

Based on the Blazor documentation

DI is a technique for accessing services configured in a central location. This can be useful in Blazor apps to:

  • Share a single instance of a service class across many components, known as a singleton service.
  • Decouple components from concrete service classes by using reference abstractions. For example, consider an interface IDataAccess for accessing data in the app. The interface is implemented by a concrete DataAccess class and registered as a service in the app’s service container. When a component uses DI to receive an IDataAccess implementation, the component isn’t coupled to the concrete type. The implementation can be swapped, perhaps for a mock implementation in unit tests.

Service Configuration

Services can be configured with one of the following lifetimes

Name Description
ScopedBlazor client-side doesn’t currently have a concept of DI scopes. Scoped-registered services behave like Singleton services. However, the server-side hosting model supports the Scoped lifetime. In a Razor component, a scoped service registration is scoped to the connection. For this reason, using scoped services is preferred for services that should be scoped to the current user, even if the current intent is to run client-side in the browser.
TransientWhen a component obtains an instance of the service it will be a new instance of that service.
SingletonDI create a single instance of the service. All component will use the same instance of the service.

Default Services

Blazor offers a basic set of services pre-configured

Name Description
HttClient By default its register has a Singleton. Provides methods for sending HTTP request and reciveing HTTP responses. This instance of HttpClient uses the browser for handling the HTTP traffic in the background.
IJSRuntimeBy default its register has a Singleton, represent an instance of a JavaScript runtime where JavaScript calls are dispatched.
IUriHelperBy default its register has a Singleton, contains helper for working with Uris and Navigation state.

Custom Service

Like I mention at the start, we have the capability to register our own custom services. We will modify the counter, we will add a service that will keep track of the counter count and it will be in charge of incrementing the counter, we will call it CounterService.

First we start by creating a Interface for the CounterService

namespace BlazorDependencyInjection.Shared.Interfaces
{
    public interface ICounterService
    {
        int Count { get; set; }
        int GetCount();
        void IncrementCount();
    }
}

Then we create the implementation

namespace BlazorDependencyInjection.Shared.Services
{
    public class CounterService : ICounterService
    {
        public int Count { get; set; } = 0;
        public int GetCount()
        {
            return Count;
        }
        public void IncrementCount()
        {
            Count++;
        }
    }
}

Register The Service

Now that we have our Service created we can register it through dependency Injection. Open the Startup   file, in the   ConfigureServices method we add our services. Note that for this post I created a Server Side Blazor project, this give me the option to register my service has a Scoped service, if you are using the Client-Side Blazor project, the service will behave has a singleton, since the end user will be the one running the app in their machine this makes sense, for the server-side, using a Singleton will make the application use the same instance of the service for anyone that uses the app. This is something to keep in mind when you register your custom service.

  public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton<WeatherForecastService>();
	    //our custom service
            services.AddScoped<ICounterService, CounterService>();
        }

Notice that when we register the service we specified the Interface and the implementation, now that we register our service how we use it? Well is actually very easy, we and inject the service in multiple ways, first we head over to the component where we want to use it, in this case, the counter page.

We can inject the service in the component directly:

@page "/counter"
@using Shared.Interfaces
@inject  ICounterService  _counterSerivice;
<h1>Counter</h1>

<p>Current count: @_counterSerivice.GetCount()</p>

<button class="btn btn-primary" @onclick="@IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        _counterSerivice.IncrementCount();
    }
}

You can also inject the service in the @code section

@page "/counter"
@using Shared.Interfaces

<h1>Counter</h1>
<p>Current count: @_counterSerivice.GetCount()</p>
<button class="btn btn-primary" @onclick="@IncrementCount">Click me</button>

@code {
    int currentCount = 0;
    [Inject]
    protected ICounterService _counterSerivice { get; set; }
    void IncrementCount()
    {
        _counterSerivice.IncrementCount();
    }
}

Since we are storing the counter on a property of the Counter Service, has long has the instance is ‘alive’ it will keep the value even if you navigate to other pages on the application. This can give developers a way to keep the state of the app, although if you want to manage the application state I will recommend using a Flux pattern or a Redux library, depend on your use case, it takes more time to set up but are worth the time when dealing with big applications.

You can download the repository and run it yourself, if you want to learn more about how to use the services already in the DI container checkout my blog post on Blazor and JavaScript, I teach you how to use the IJSRuntime service. If you didn’t understand something or wish to learn more I’m more than happy to help.