Blazor Lifetime

Let us look at the lifetime of injected dependencies in Blazor.

Dependency Injection in Blazor

.NET Core dependency injection allows you to choose between 3 difference lifetimes

  • Singleton
  • Transient
  • Scoped

As an experiment I have built a simple application to look at instance lifetimes.

I started by building three services, each one with a different lifetime. For example:

public class ScopedService
{
  public Guid Guid { get; set; }

  public ScopedService()
    => Guid = Guid.NewGuid();
}

Then I added these three services to the service collection:

services.AddSingleton<SingletonService>();
services.AddTransient<TransientService>();
services.AddScoped<ScopedService>();

And finally I consume these services in a simple component, which I am using in two separate pages because this will allow me to switch from one to the other.

<div>
  <h1>Singleton</h1>
  Guid: @singletonService.Guid
  <h1>Transient</h1>
  Guid: @transientService.Guid
  <h1>Scoped</h1>
  Guid: @scopedService.Guid
</div>

@inject SingletonService  singletonService  
@inject TransientService transientService
@inject ScopedService scopedService

Client-Side Blazor Experiment

Running this as a client-side Blazor project we get the following on the first page

/Blazor/Lifetimes/CSB_FirstPage.png

and switching to another page in the same tab.

/Blazor/Lifetimes/CSB_OtherPage.png

Switching to another tab we get:

/Blazor/Lifetimes/CSB_OtherTabFirstPage.png

And then to the other page on the other tab:

/Blazor/Lifetimes/CSB_OtherTabOtherPage.png

Service-Side Blazor Experiment

Visiting the first page:

/Blazor/Lifetimes/SSB_FirstPage.png

Switching to the other page:

/Blazor/Lifetimes/SSB_OtherPage.png

Then swithing to another tab

/Blazor/Lifetimes/SSB_OtherTabFirstPage.png

And finally swithing to another page on the other tab

/Blazor/Lifetimes/SSB_OtherTabFirstPage.png

The Result of the Experiment

Transient lifetime

This one is easy. Transient lifetime means you get a new instance every time.

Singleton lifetime

Again easy. With a Singleton you get the same instance every time. Easy? Not so fast buddy!!!

With Blazor we have server-side and client-side. With server-side Blazor a Singleton gets shared by every one on that server, because it is scoped to the server instance. Everybody gets the same instance.

But with client-side Blazor the same instance (of Singleton) is scoped to your Browser's tab, because the Singleton is scoped to the WASM application! Open two tabs in the same browser, and you get two instances of that Singleton. If you really need a Singleton with CSB you need to use a server-side singleton and use REST calls.

Scoped lifetime

Blazor documentation clearly states that with client-side Blazor a scoped instance is the same as a Singleton instance, because the scope is the application. This is what we see in this experiment. Please use Scoped instances if you need the instance to correspond to the user.

For service-side Blazor the Scope is linked to the connection of the user. If the same user opens two tabs in the same browser, each tab receives its own instance of the Scoped instance.

For both CSB and SSB, if you need to have the same instance, no matter which tab the user is using, you cannot rely on dependency injection to do this for you. You will need to do some state handling yourself!