I am experiencing a weird behavior while trying to use a Scoped Service that I am initializing in the _Host.cshtml file. This is the service, which is very simple:
public interface IUserSessionService
{
void SetUserData(UserSessionData userData);
UserSessionData GetUserData();
}
public class UserSessionService : IUserSessionService
{
private UserSessionData userSessionData;
public void SetUserData(UserSessionData userData)
{
userSessionData = userData;
}
public UserSessionData GetUserData()
{
return userSessionData;
}
}
The service is registered as Scoped service in the Startup.cs
file
services.AddScoped<IUserSessionService, UserSessionService>();
The service gets user information from a database in the following fashion in the code behind the host.cshtml page:
public class _Host : PageModel
{
private readonly IUserSessionService userSessionService;
public _Host(IUserSessionService userSessionService)
{
this.userSessionService = userSessionService;
}
public async Task OnGet()
{
var authenticatedUser = Request.HttpContext.User;
var userData = await GetUserDataFromDb(authenticatedUser);
await userSessionService.SetUserData(userData);
}
}
Ideally, I would expect this to initialize the service, so that from now on I can inject it in my components and access to the user's information whenever I need it.
This is not working though: when the page loads I am able to see the user information in the screen for a second, then it disappears. Initially I thought it was caused by the page render mode ServerPrerendered
, however in Server
mode the issue persists.
The only fix I could find is to register the service as Singleton
; that is not ideal as that would be shared between all the users (at least that is my understanding!).
Is there a better place where I can store this information?
UPDATE
The issue was mostly the consequence of my bad understanding of how the Blazor circuit works :) I got it working following @enet's advice. What I did is:
- Got the information from the
HttpContext
in aHostModel
class created for_Host.cshtml
and made it available to the html code with a property
public class HostModel : PageModel
{
public UserSessionData UserSessionData { get; private set; }
// ... set the information up
}
- create a parameter in the ComponentTagHelper and pass the property data
@model HostModel
<component type="typeof(App)" render-mode="ServerPrerendered" param-UserSessionData="@Model.UserSessionData" />
- Access the information as
[Parameter]
in theApp.razor
@code {
[Parameter]
public UserSessionData UserSessionData { get; set; }
}
- Setup the information in the scoped service inside the
OnInitializedAsync()
method
protected override async Task OnInitializedAsync()
{
await UserSessionService.SetUserData(UserSessionData);
}
Now the UserSessionData
will be available everywhere in the application through the injection of the IUserSessionService