---
title: "Lifetime Scope in Blazor Client and Server Apps "
description: "You probably are well aware of the Lifetime Scope for ASP.NET Core website.\nThere are basically 3 scopes: `Transient`, `Scoped` and `Singleton`. Let's have a look how they differ in Blazor Client and Server."
updated: 2021-11-24
tags: ["Blazor", "Lifetime", "DI"]
canonical: "https://steven-giesel.com/blogPost/1548e20a-211b-419b-8a9e-ded05b59a179/lifetime-scope-in-blazor-client-and-server-apps-"
---

# Lifetime Scope in Blazor Client and Server Apps 

## Short Summary
We basically know 3 types of lifetimes when it come to ASP.NET Core

 * **Singleton** - One instance is created and is shared across all users
 * **Transient** - Whenever someone is asking for a service always a new instance is created
 * **Scoped** - One instance per request

## Setup
Let's create three services, for each lifetime one:
```csharp
public class MySingletonService
{
    public Guid ServiceId { get; set; } = Guid.NewGuid();
}

public class MyScopedService
{
    public Guid ServiceId { get; set; } = Guid.NewGuid();
}

public class MyTransientService
{
    public Guid ServiceId { get; set; } = Guid.NewGuid();
}
```

Now we need two pages. We reuse the template which comes shipped with Visual Studio.
Therefore we adapt the Index.razor and Counter.razor in this way:
```csharp
@page "/"
@inject MySingletonService singletonService
@inject MyScopedService scopedService
@inject MyTransientService transientService

<h1>Index</h1>
<ul>
    <li>Singleton Service - @singletonService.ServiceId</li>
    <li>Scoped Service - @scopedService.ServiceId</li>
    <li>Transient Service - @transientService.ServiceId</li>
</ul>
```

```csharp
@page "/"
@inject MySingletonService singletonService
@inject MyScopedService scopedService
@inject MyTransientService transientService

<h1>Counter</h1>
<ul>
    <li>Singleton Service - @singletonService.ServiceId</li>
    <li>Scoped Service - @scopedService.ServiceId</li>
    <li>Transient Service - @transientService.ServiceId</li>
</ul>
```
They look the same only the header is different. Now we want to check a few scenarios:
 * Start the app and land on our home page
 * Navigate to the counter page from the navigation menu
 * Reload the index page with F5
 * Open the page in incognito mode

## Blazor Client
Now we have a look how the ID's look on the client side

|           | Home page                            | Navigate to counter                  | Hard reload                          | Incognito mode                       |
|-----------|--------------------------------------|--------------------------------------|--------------------------------------|--------------------------------------|
| Singleton | 17bbf702-b870-4242-a016-53440d85c30c | 17bbf702-b870-4242-a016-53440d85c30c | 2cde0cc6-792d-4f24-8752-6662996e506b | 9ed59027-9a43-45ec-827e-2bc6e8fcde5c |
| Scoped    | 5526f6ea-0bfe-44fe-8264-a902286ec165 | 5526f6ea-0bfe-44fe-8264-a902286ec165 | ada9205d-af01-4c1b-86b5-de840f02cce5 | 7b6283d1-fdef-4a49-850d-c1a78111a849 |
| Transient | 96707761-be74-4cf7-94d6-3fc940f9d016 | 732ed661-e833-4537-a7bf-9691f81d58bd | f218f73b-93b7-43d6-9cf2-f9a08960c489 | 036b450b-c486-49e5-9a9c-07b22f4e5713 |

Now let's have a look. First the obvious one: **Transient**. I guess it is not weird that all of the services are unique. Now let's come to **Singleton**. Why is it different for Hard reload and incognito? The answer is easy: The code runs on your local machine and not on a server, therefore this is basically like a new program running which initializes the container once more.
Now **Scoped**: Why do we have the same ID when we navigate to a different page? Well that is the idea behind a single page application. You don't make a new "request". You are still in the same request as you started. That also explains why a hard reload gives you a new ID, because now we have a new request.

Let's go to the server side

## Blazor Server
|           | Home page                            | Navigate to counter                  | Hard reload                          | Incognito mode                       |
|-----------|--------------------------------------|--------------------------------------|--------------------------------------|--------------------------------------|
| Singleton | 76844a38-eca3-4b75-b47a-1f3bbc5510c9 | 76844a38-eca3-4b75-b47a-1f3bbc5510c9 | 76844a38-eca3-4b75-b47a-1f3bbc5510c9 | 76844a38-eca3-4b75-b47a-1f3bbc5510c9 |
| Scoped    | a434c2f8-6e15-4787-bfc8-530cc1aebc9e | a434c2f8-6e15-4787-bfc8-530cc1aebc9e | 16f56278-38bc-4c88-a804-38d8682c655a | e3d32065-f79f-4812-adc1-5b8ad9176e0c |
| Transient | ad787879-a91e-4721-820b-95481cd90a85 | 55a993dd-22de-42e5-ad92-4e69666462e6 | b4a5e6b2-5eb6-494d-b8df-9a9c763ca5c3 | 8fc3bc62-c4f8-4794-8ef6-6ff0b963950b |

The not surprising part first: We have the same picture for **Transient** in client as well as server. If we have a look at the **Singleton** we see a difference. The incognito mode does not lead to a new instance. And that makes sense, because actually the server is the same. Blazor server "just" opens a SignalR connection with the HTML content rendered by the server. The main book of work is done on the server. Last but not least **Scoped**. We see the exact same picture as with the client side blazor. Of course client and server share a lot of similarities and this is also true for the **Scoped** lifetime.

## Conclusion
Blazor client and server have a slightly different lifetime scope than your "normal" ASP.NET Core Web API or MVC project.