0

im using blazor server side and are therefore trying to use AddScoped instead of AddSingleton as the object is used on a per-user basis. I try to split the razor pages and the c# code as much as posible as i find this to be cleaner.

I add a scoped service using

Services.AddScoped<Services.ManageUserService>();

in the ConfigureServices function of the Startup class.

my problem now is to properly access the service from any .cs file (holding the logic of my .razor pages)

I have tried to do an injection like this:

[Inject]
public Services.ManageUserService manageUserService { get; set; }

and then accesed the scoped object using (username for example):

manageUserService.User

and this works. My problem is that if I add a print that is supose to only run once within the scoped service it runs every time the page is reloaded or changed.

for example, lets say i do this:

public class ManageUserService
{
    public string User { get; private set; }

    private bool LoadedStartup = false;

    public ManageUserService() => SetupUser();

    private void SetupUser()
    {
        if (!LoadedStartup)
        {
            User = "me";
            LoadedStartup = true;
            System.Diagnostics.Debug.Print("User:" + User);
        }
    }
}

I then access the class from multiply .cs files using:

[Inject]
public Services.ManageUserService manageUserService { get; set; }

The print "User:me" is supposed to only happen once as the locking bool LoadedStartup is changed, problem is that I get the print every time the Inject is happening (on change page, etc)

What am I doing wrong? aren't the AddScoped() suppose to add a "singelton" instance for every client? am I accessing it wrongly?

I can't find any examples of using AddScoped from separated .cs and .razor pages, only directly from the .razor page, and then it is done using @inject.

1 Answer 1

1

I was in the same situation:

1.- Add the scoped services:

Services.AddScoped<Services.ManageUserService>();

2.- Then, in order to have really the scoped instances once per user, in _Hosts.cshtml:

<app>
 <component type="typeof(App)" render-mode="Server" />
</app>

3.- Now the trick I found by myself, instance the scoped services in App.razor

@inject Examples.ViewModels.MainViewModel Main;
@inject Examples.ViewModels.ChildViewModel Child;
@inject Examples.ViewModels.LayoutViewModel Layout;
@inject Examples.ViewModels.TreeViewModel Tree;
@{

Child.Main = Main;
Tree.LayoutViewModel = Layout;
}

4.- And if you have in the constructor something like:

public class MainViewModel
{
  public static MainViewModel Instance;
  public MainViewModel()
  {
  Instance = this;
 }

}

You can access to any class you define as service from anywhere in your code.

 MainViewModel.Instance...

I post about it at my blog: https://expediteapps.net/2020/02/18/scoped-viewmodels-instanced-once-on-start/

Sign up to request clarification or add additional context in comments.

1 Comment

thats a rly nice answere to a problem thats been driving me mad (and rly should be easy to solve), will try it out and accept it if it works! thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.