C
C#4mo ago
Byron

How to Initialize Scoped Service in Blazor Web App before page is loaded?

protected override async Task OnInitializedAsync()
{
AuthService.CurrentUser ??= await IdentityService.GetUserContext();
if (!TodoService.IsInitialized) await TodoService.InitAsync();
}
protected override async Task OnInitializedAsync()
{
AuthService.CurrentUser ??= await IdentityService.GetUserContext();
if (!TodoService.IsInitialized) await TodoService.InitAsync();
}
My issue is that if this goes in MainLayout, then its data is not guaranteed to be available in OnInitializedAsync of each razor page. If this goes in App.Razor, the scoped service data is being reset, and is no longer available when I get to the page.
9 Replies
SleepWellPupper
SleepWellPupper4mo ago
You could implement a scoped TodoServiceProvider with a method Task GetTodoService(), which internally manages initialization. Same for your auth context
Byron
ByronOP4mo ago
Would this be a replacement for AddScoped(TodoService) in Program.cs So I only register the provider?
SleepWellPupper
SleepWellPupper4mo ago
You would register both your todo service, and the provider; inject the todo service into the provider and make sure it's initialized before returning from the get method. Both should be scoped.
Byron
ByronOP4mo ago
At a high level is the solution here that I need to have my service manage its own initialization? So that the service does not depend on the app to initialize it?
SleepWellPupper
SleepWellPupper4mo ago
Hm maybe. You are looking at temporal coupling, which means the correct state of an object depends on the order of methods called on it. Here's an article about it: https://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/ One solution is to provide access to the initialized object via some other, like a factory (or provider, in your case).
Byron
ByronOP4mo ago
TY! That helped a lot. For something like this that has to be initialized a lot I see where that gets complicated to enforce it is initialized. In my case I just switched to caching the data (User Service) since it is a small Id needed on many requests. And i made the other a singleton and initialized in Program.cs which I think is ok since it is being initialized once at startuo
SleepWellPupper
SleepWellPupper4mo ago
Any dependency injected into a singleton will inherit that lifetime, so be aware of that.
Byron
ByronOP3mo ago
I added IDbContextFactory for my EF context on the singleton service. It only pulls the data once but I think this will work if I need to Init again in the future I hate having this state stored in properties of the singleton, vs something specific to the client but I think in blazor server sometimes you just have to combine backend/frontend things since that is the benefit of using this framework
SleepWellPupper
SleepWellPupper3mo ago
DbContext should never be a singleton, this will cause concurrency errors (DbContext is not threadsafe) and performance issues (DbContext is intended to be short lived and multifarious, i.e. one per user and thus lots of them)

Did you find this page helpful?