Jens Mander
Jens Mander

Reputation: 490

Initialize Service in Blazor Webassembly

I've got a service A that is shared among various components. That service needs to be initialized at startup with values from a WebApi.

How can I accomplish that? I tried two things.

_1.

In program.cs/main method I do

builder.Services.AddScoped

with A and other services B and C.

Then I call a method

async LoadSetupData(wasmBuilder)

which gets services A, B, C via

wasmBuilder.GetRequiredService<T(A)>...

and then

A.MySetupValues = await B.GetSetupValues().

The values are retrieved through the WebApi.

That works so far. But when I use A in a component via [Inject] A a, the service object I get is not the one I retrieved in LoadSetupData (service has a Guid property, they are different).

_2.

I tried adding A by providing a factory method to AddScoped. That doesn't work because getting Values from a WebApi is intrinsically asynchronous. And asynchronous calls can't be used from program.cs/main ("Cannot wait on monitors on this runtime").

Thank you very much for reading! Any help is highly appreciated!

Upvotes: 2

Views: 4459

Answers (3)

Jens Mander
Jens Mander

Reputation: 490

Thanks for all of your answers! I was able to resolve the problem by doing the Initialization in the App Component in OnInitializedAsync.

[Inject] IServiceProvider sp { get; set; }

protected override async Task OnInitializedAsync() {

  ISvcB svcb = sp.GetRequiredService<ISvcB>();
  ISvcA svca = sp.GetRequiredService<ISvcA>();

  svca.SetupData = await svcb.GetSetupData();
}

Upvotes: 3

Nicola Biada
Nicola Biada

Reputation: 2800

Try to redefine your design.

I prefer to have all the initialization of the service in the constructor.
You need some other services (B & C), so you need to use DI in the constructor of the service A.

SOLUTION "A"

I think the following design should work for your case:

builder.Services.AddScoped<IServiceA,ServiceA>();

var hostInstance = builder.services.Build();
var theServiceA = hostInstance.GetRequiredService<IServiceA>();

...

hostInstance.RunAsync()

SOLUTION "B"

Try this one in alternatives:

builder.Services.AddScoped(sp => sp.GetRequiredService<IServiceA>().LoadSetupData());

Just a note to anyone, in Blazor WASM Scoped and Singleton life time are the same. Not in Server.

Upvotes: 0

Christophe Debove
Christophe Debove

Reputation: 6306

In the Program.cs you can load your data and then indicate how to resolve the dependancy injection.

var datas = await (new TheProvidingDataService()).LoadDataAsync();
builder.Services.AddSingleton(s => new NeedYourDataService(data));

Upvotes: 2

Related Questions