Blazor Server, служба с ограниченной областью действия в промежуточном программном обеспечении не хранит данныеC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Blazor Server, служба с ограниченной областью действия в промежуточном программном обеспечении не хранит данные

Сообщение Anonymous »


The data is not saved within a DI Scoped Service when using Middleware after Identity login. In this example, the data is always "false" even though it has been set to "true" (confirmed in the debugger).

I'm attempting to load the user's data in PostAuthenticationMiddleware.cs. I believe this is called after login.

How can I load the user data after logging in and retrieve it throughout the Blazor Server application?

EDIT #2: It appears that my approach of using app.UseMiddleware(); is incorrect. I've modified this to use a Scoped service that hooks onto AuthenticationStateProvider's AuthenticationStateChanged. I would expect this to fire when the User logs in, etc. However, this event is not firing. How do I get this event to fire? Or what is the preferred way to load user data from within Blazor Server after login? This data should be available throughout the application. I am assuming this should be in a Scoped Service.

LoginService.cs:

public class LoginService : IDisposable { private readonly AuthenticationStateProvider _authenticationStateProvider; public string SomeUserData { get; set; } = ""; // We'll store data for the User here. public Guid TestUnique { get; set; } = Guid.NewGuid(); // To check that this service is Scoped. public LoginService(AuthenticationStateProvider authenticationStateProvider) { _authenticationStateProvider = authenticationStateProvider; // Subscribe to the authentication state changes with the correct method signature _authenticationStateProvider.AuthenticationStateChanged += AuthenticationStateChangedAsync; } private async void AuthenticationStateChangedAsync(Task task) { // *** This isn't being fired *** var authState = await task; var user = authState.User; if (user.Identity.IsAuthenticated) { // Load the user data from the database SomeUserData = "data from database!"; } else { SomeUserData = ""; } } public void Dispose() { // Unsubscribe from the authentication state changes to avoid memory leaks _authenticationStateProvider.AuthenticationStateChanged -= AuthenticationStateChangedAsync; } } Progam.cs (modified to include)

// ... template generated code builder.Services.AddScoped(); // Added scoped service var app = builder.Build(); // template generated code ... Yet, AuthenticationStateChangedAsync does not fire. Why?

EDIT #1: I've tried saving the user details after login in MainLayout.razor, however this sometimes causes a race condition and the values aren't set before the target page is loaded. Where is the correct place to load in user related data after login in Blazor Server?


Изображение


_Host.cshtml

@page "/" @namespace Blazor_Identity_Middleware_Scoped_Poc.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } Program.cs

using Blazor_Identity_Middleware_Scoped_Poc.Areas.Identity; using Blazor_Identity_Middleware_Scoped_Poc.Data; using Blazor_Identity_Middleware_Scoped_Poc.Services; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.UI; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); // added scoped service var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware(); // added middleware to fire event after login, this loads the UserData app.MapControllers(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run(); UserData.cs

namespace Blazor_Identity_Middleware_Scoped_Poc.Services { public class UserData { public bool SomeUserData { get; set; } = false; } } PostAuthenticationMiddleware.cs

using Microsoft.AspNetCore.Identity; using Microsoft.Data.SqlClient; namespace Blazor_Identity_Middleware_Scoped_Poc.Services { public class PostAuthenticationMiddleware { private readonly RequestDelegate _next; public PostAuthenticationMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, UserData userData, UserManager userManager) { if (context.User.Identity.IsAuthenticated) { // User is authenticated; perform your actions here // You can retrieve the user from the UserManager using the user's name or ID var user = await userManager.GetUserAsync(context.User); if (user != null) { // Do we have any data? if (userData.SomeUserData == false) { // We'll load the user data from the database. // However... This is called 4 times. Console.WriteLine("userData.SomeUserData is false"); userData.SomeUserData = true; } else { // This is never called. Console.WriteLine("userData.SomeUserData is true"); } } } // Call the next delegate/middleware in the pipeline await _next(context); } } } Counter.razor

@page "/counter" @using Blazor_Identity_Middleware_Scoped_Poc.Services @using Microsoft.AspNetCore.Components.Authorization @using System.Security.Claims @inject AuthenticationStateProvider AuthenticationStateProvider @inject UserData UserData Counter Counter Current count: @currentCount
Click me @if (user.Identity.IsAuthenticated) {
Welcome, @user.Identity.Name!
} else {
You are not logged in.
} SomeUserData: @UserData.SomeUserData @code { private int currentCount = 0; private ClaimsPrincipal user; protected override async Task OnInitializedAsync() { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); user = authState.User; } private void IncrementCount() { currentCount++; } }

Источник: https://stackoverflow.com/questions/780 ... eping-data
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»