1

This is for Blazor (server).

According to this documentation, session scope for a service in Blazor (server side) means:

Scoped services aren't reconstructed when navigating among components on the client, where the communication to the server takes place over the SignalR connection of the user's circuit, not via HTTP requests.

And in this blog article (seems to be knowledgable):

It creates a scope for each so-called “circuit”. A circuit is created when a new browser tab connects to the Blazor server via the underlying SignalR transport, and it is terminated when the browser tab is closed again (or if the connection is lost and fails to reconnect within a specified time frame).

But in this Microsoft Q&A it says:

If this is a Blazor Server question then scoped behaves like a singleton. The official documentation covers how service life time works..

I think a singleton is the same object across all circuits/sessions. The documentation is as follows.

DI creates a single instance of the service. All components requiring a Singleton service receive the same instance of the service.

Of course "all components" can mean all components in a single circuit/session. Or it can mean all components across all circuits/sessions. I can see how if the "all components" is per circuit/session, then scoped is the same as singleton for most (all) use cases. But if singleton is a single instance across ever circuit/session, then they differ - a lot.

So what exactly is going on for scoped & singleton services on Blazor server?


Summary

The discussion on this got emotional (which I hate to see) and there is a lot of valuable discussion of this question in the two answers below. So no disrespect to them but I am going to summarize the answer here.

A singleton will return the same instance on every call. Good example of a use here, getting the sales tax rate for a location (like Boulder, Colorado). That information is the same for every user.

A scoped will return a different instance for each SignalR circuit (often referred to as scope in Blazor server). For the life of a circuit it will keep returning the same instance to that circuit/session. Good example here is a shopping cart.

What can lead to some confusion - both a singleton and scoped service will return the same instance for the life of the circuit. In that way they are identical.

But if there are two circuits to your server, the singleton will return the same instance to both while the scoped service will return a different instance to each. In this way they are very different.

David Thielen
  • 28,723
  • 34
  • 119
  • 193

2 Answers2

3

Putting all 3 doc cites together, you should read:

  • Any session connects to a Blazor server via SignalR
  • When the session starts a new scope for that session is created

From now on we can treat session and scope as the same, because each session has its own scope that will survive until the session ends.

  • Within a scope (which in this context is equal to session) there is no difference between services with a scoped or singleton lifetime, as we will get for both the same instance from the ServiceProvider again and again.

That what is meant be scoped behaves like a singleton, and you should also consider the first part If this is a Blazor Server question then. Seems most Blazor Server questions has to be treated in the context of a session, and because each session has its own scoped, which never changes ...

That is different to normal ASP.NET Server, where you get a new scope for each request.

I guess the most problems came up with DbContext as that is as scoped service and in ASP.NET you have a clean fresh context on every request. But with Blazor Server you can now have side effects because it is not fresh and clean anymore and maybe dirty from an older use within the current session.

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • But if I have 2 sessions ongoing, then they have distinct scoped services but a shared singleton service - correct? In that case, while the lifespans are the same, the sharing, or not for scoped, is very different? – David Thielen May 08 '23 at 05:59
  • Yes, of course. There is and was no change in DI container, but what "changed" is the scoped lifetime, which is with ASP.NET per request no matter of the session but with Blazor Server the scoped lifetime is spanned over the whole session. That is/was a pitfall for developers coming from ASP.NET to Blazor Server. – Sir Rufo May 08 '23 at 06:38
  • @DavidThielen. As explained by @SirRufo `Scoped` has a very different meaning in Blazor to that in a normal server side application. If you want your service scoped to the lifespan of your page, there's no service scope that you can inject into a page and it's sub components, that goes "out of scope" when the page is destroyed. You can't use `Transient` because you get a new instance each time you inject it, and `OwningComponentBase` is useless in most situations. See this answer that explains further and provides some solutions - https://stackoverflow.com/a/75555540/13065781 – MrC aka Shaun Curtis May 08 '23 at 16:09
  • @MrCakaShaunCurtis scoped is what I want - a lifespan tied to the circuit/session. I asked because the Msft tech said it was the same as singleton and I don't want it shared between circuits. The answers here make it clear it does work as I thought. thanks – David Thielen May 09 '23 at 06:09
2

What's going on is that they differ a lot.

Scoped services persist so long as a user keeps their circuit, i.e. they are connected. They are unique to that connection (basically, that browser tab while it is open).

Singleton services persist forever, and are shared by everyone. This allows you, for example, to send a message to all connected users, or to allow chat between multiple users in a group.

A typical usage for a game server would be to have a Singleton service to handle game rooms and game instances, and a Scoped service for each user which subscribes to it.

It's a little confusing when learning Blazor, because when you're alone on a dev machine, your experience of both will be exactly the same unless you open your site on multiple tabs / browsers.

Bennyboy1973
  • 3,413
  • 2
  • 11
  • 16
  • This is what I thought it is. What's key is singleton is shared, scoped isn't. – David Thielen May 08 '23 at 06:00
  • But that is business as usual, that is how the DI container works for years. There was no change in transient, scoped or singleton lifetime. And the docs you cited did not tell anything different. – Sir Rufo May 08 '23 at 06:42
  • @SirRufo I asked because in [this](https://learn.microsoft.com/en-us/answers/questions/1279324/what-does-scoped-lifetime-for-a-service-mean-in-bl) the Microsoft tech was insisting that scoped == singleton. I figured he was wrong but figured better to check as his job is answering questions on Blazor. And I think he got hung up on the lifetime to a circuit/session is the same for both. True. But it's critical to realize singleton is shared, scoped is not and he did not speak to that or take it into consideration. – David Thielen May 08 '23 at 13:54
  • @DavidThielen You asked "Does that mean the lifetime of a connection so a user session? Or does that mean once per http request" and the ms tech aswered - in short - that it depends on if you are using Blazor Server or not. Anything other then Blazor Server the scope is bound to the request but with Blazor Server the scope is bound to the session. And with no word did he said scoped==singleton! In Blazor Server the scoped **behaves like** singleton (when you stay in the same session) – Sir Rufo May 08 '23 at 15:22
  • @SirRufo I understand where you and the Msft tech are coming from in that the lifespan is the same. But I would never say they're the same because one is per circuit and one is shared across all circuits. I'd refer to the original question that kicked this all off, but it appears to have been deleted from the Microsoft site. – David Thielen May 09 '23 at 06:12
  • @DavidThielen Who on earth did say they are the same? "scoped **behaves like** singleton" (in context of the same Blazor Server session) is something completely different what you got from it "scoped is the same as singleton". – Sir Rufo May 09 '23 at 08:49
  • @DavidThielen Nothing is kicked off, you are just having problems in posting links. In [this question](https://learn.microsoft.com/en-us/answers/questions/1279324/what-does-scoped-lifetime-for-a-service-mean-in-bl) you try to link to the original question, but you failed and linked the link to back to self building a link circle. Copy'Paste the text of the link and you will get [to the original question](https://learn.microsoft.com/en-us/answers/questions/1276643/should-this-be-transient-scoped-(and-is-it-a-good)) – Sir Rufo May 09 '23 at 08:55
  • @SirRufo no offense, but what you are saying is not correct. A singleton most certainly does not act like a scoped service. If anyone makes this error, they will completely bork their website as soon as 2 circuits are connected. For maxium hilarity, store important user information in a field in a singleton service, and watch the lawsuits roll in! – Bennyboy1973 May 09 '23 at 09:26
  • 1
    @Bennyboy1973 We are talking about "scoped **behaves like** a singleton" (in the context of a Blazor Server session) and NOT the other way around. Noone ever here was saying that "singleton act like a scoped". – Sir Rufo May 09 '23 at 09:46
  • It doesn't matter which order you put them in. One has this behavior: it shares itself across all sessions. One has this behavior: it is an instance which applies only to a specific circuit (i.e. an open browser tab). Neither one behaves like the other-- unless you are using WASM, in which no data is ever shared with other sessions, because there are none to share with. But the question clearly indicates that the OP is talking about the server flavor of Blazor. – Bennyboy1973 May 09 '23 at 10:12
  • @Bennyboy1973 Thank you - I was worried I was not being clear. – David Thielen May 10 '23 at 09:07