I'm facing an issue and I'm not sure who to ask for help. Could you please provide me with some suggestions? I've been unable to find my mistake despite my research.I've implemented user authentication in a Blazor .NET 8 server application, where I'm trying to store user information using session storage until they log out. On the homepage, I have some charts, and when I refresh the page to check if the user session is still valid, it fails and gives me this error.
using BlazorApp4.Services;
using Blazored.SessionStorage;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private ISessionStorageService _sessionStorage;
private IUserService _userService;
public CustomAuthenticationStateProvider(ISessionStorageService sessionStorage, IUserService userService)
{
_sessionStorage = sessionStorage;
_userService = userService;
}
//prerendering sırasında ya da kullanıcı bilgisi olmadığında anonim kimlik döndürür
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
return Task.FromResult(new AuthenticationState(anonymousUser));
}
public async Task LoadUserStateAsync()
{
var username = await _sessionStorage.GetItemAsStringAsync("username");
ClaimsIdentity identity;
if (!string.IsNullOrEmpty(username))
{
identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, username) }, "CustomAuthType");
}
else
{
identity = new ClaimsIdentity();
}
var user = new ClaimsPrincipal(identity);
var currentState = new AuthenticationState(user);
//var snapshot = new AuthenticationState(new ClaimsPrincipal(identity));
//await Task.Yield();
NotifyAuthenticationStateChanged(Task.FromResult(currentState));
}
//public async Task LoadUserStateAsync()
//{
// var username = await _sessionStorage.GetItemAsStringAsync("username");
// ClaimsIdentity identity = !string.IsNullOrEmpty(username)
// ? new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, username) }, "CustomAuthType")
// : new ClaimsIdentity();
// var user = new ClaimsPrincipal(identity);
// NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
//}
public async Task<bool> MarkUserAsAuthenticated(string username, string password)
{
var user = await _userService.ValidateUserCredentials(username, password);
if (user != null)
{
await _sessionStorage.SetItemAsStringAsync("username", username);
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, username),
}, CookieAuthenticationDefaults.AuthenticationScheme);
var userPrincipal = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(userPrincipal)));
return true;
}
return false;
}
public async Task MarkUserAsLoggedOut()
{
await _sessionStorage.RemoveItemAsync("username");
var identity = new ClaimsIdentity();
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
}
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.FluentUI.AspNetCore.Components
@inherits LayoutComponentBase
@using FluentOrientation = Microsoft.FluentUI.AspNetCore.Components.Orientation;
@inject AuthenticationStateProvider AuthenticationStateProvider
<FluentLayout >
<FluentHeader>
Blazor App
</FluentHeader>
<CultureSelector />
<FluentStack Orientation="FluentOrientation.Horizontal" Width="100%">
<div>
<FluentNavMenu @bind-Expanded="@Expanded" Width="200" Collapsible="true" Title="App Navigation Menu">
<AuthorizeView>
<Authorized>
<FluentNavLink Href="/" Icon="@(new Icons.Regular.Size24.Home())">Anasayfa</FluentNavLink>
<FluentNavLink Href="personals" Icon="@(new Icons.Regular.Size24.People())">Personel Listesi</FluentNavLink>
<FluentNavLink Href="Account/Logout">Çıkış Yap</FluentNavLink>
</Authorized>
<NotAuthorized>
<FluentNavLink Href="Account/Login">Giriş Yap</FluentNavLink>
</NotAuthorized>
</AuthorizeView>
</FluentNavMenu>
</div>
<FluentBodyContent>
<div class="content">
@Body
</div>
</FluentBodyContent>
<FluentToastProvider @rendermode=@InteractiveServer />
<FluentDialogProvider @rendermode=@InteractiveServer />
<FluentTooltipProvider @rendermode=@InteractiveServer />
<FluentMessageBarProvider @rendermode=@InteractiveServer />
</FluentStack>
</FluentLayout>
@code
{
bool Expanded = true;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await ((CustomAuthenticationStateProvider)AuthenticationStateProvider).LoadUserStateAsync();
StateHasChanged();
}
}
}
@page "/"
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.Extensions.Localization
@using System.Text.Json
@using global::Microsoft.AspNetCore.Components;
@using Microsoft.FluentUI.AspNetCore.Components;
@using Microsoft.AspNetCore.Authorization
@inject IStringLocalizer<Resource> Loc
@inject PersonalService PersonalService
@inject IDbContextFactory<BlazorAppDbContext> DbFactory
@inject IJSRuntime JS
@inject IAuthorizationService AuthorizationService
@implements IAsyncDisposable
@attribute [Authorize]
@* <PageTitle>@Loc["PageTitle"]</PageTitle>
<h1>@Loc["HomeText"]</h1>
@Thread.CurrentThread.CurrentCulture;
@Thread.CurrentThread.CurrentUICulture;
@Loc["HomeText"] *@
<h4 class="personalNumber">Personel Sayısı: @personalCount</h4>
@*Charts*@
<div style="display:flex; margin:30px">
<div id="sortedBarChart"></div>
<div id="chartdiv"></div>
</div>
@* <FluentButton @onclick="GeneratePieChart">Pie Chart</FluentButton> *@
<div style="display:flex; margin:30px">
<div id="variableRadiusPie"></div>
</div>
@code {
private int personalCount;
private BlazorAppDbContext Context { get; set; }
//private IQueryable<Personal>? Personal;
private List<PersonalViewModal> PersonalChartsList = new List<PersonalViewModal>();
[CascadingParameter]
public Task<AuthenticationState> AuthState{ get; set; }
protected override async Task OnInitializedAsync()
{
Context = DbFactory.CreateDbContext();
PersonalChartsList = await PersonalService.GetPersonalRolesCount();
personalCount = await PersonalService.GetPersonalCountAsync();
}
//javascript fonksiyonlarını render işlemi tamamlandıktan sonra çalışmaktadır, amCharts gösterebilmek için
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await GeneratePieChart();
await GenerateSortedBarChart();
await GenerateVariableRadiusPieChart();
}
}
public async ValueTask DisposeAsync()
{
try
{
// JavaScript tarafındaki kaynakları temizleme fonksiyonu
await JS.InvokeVoidAsync("deInitializeCharts");
}
catch (JSDisconnectedException)
{
//bağlantı kesildiğinde oluşacak hataları yoksaymak için
}
}
//Serializer işlemi
public async Task JsSerializerMethodAsync(string methodName, object data)
{
var jsonData = JsonSerializer.Serialize(data);
//chart.js yönlendirme
await JS.InvokeVoidAsync(methodName, jsonData);
}
public string GetLocalizedRoleName(string role)
{
var key = $"RolesEnum_{Enum.Parse<EnumDeclarations.RolesEnum>(role)}";
return Loc[key];
}
public string GetLocalizedIsActiveName(string value)
{
var key = $"IsActiveEnum_{Enum.Parse<EnumDeclarations.IsActive>(value)}";
return Loc[key];
}
private async Task GeneratePieChart()
{
// int activeUserCount = await Context.Personal.CountAsync(p => p.Active == "Active");
// int inActiveUserCount = await Context.Personal.CountAsync(p => p.Active == "InActive");
// var chartPieData = new[]
// {
// new { category = "Aktif", value = activeUserCount },
// new { category = "Pasif", value = inActiveUserCount }
// };
var isActiveCount = await PersonalService.IsActiveStatusCount();
var chartPieData = isActiveCount.Select(p => new
{
status = GetLocalizedIsActiveName(p.ActiveCharts),
value = p.IsActiveCount
}).ToArray();
//Blazordaki verileri javascripte fonksiyonuna aktarabilmek için
// var jsonData = JsonSerializer.Serialize(chartPieData);
// await JS.InvokeVoidAsync("CreatePieChartFromJson", jsonData);
await JsSerializerMethodAsync("CreatePieChartFromJson", chartPieData);
}
public async Task GenerateSortedBarChart()
{
var personalRolesCount = await PersonalService.GetPersonalRolesCount();
//charts içerisinde göstereliecek değerlerin atanması
var chartSortedBar = personalRolesCount.Select(p => new
{
roles = GetLocalizedRoleName(p.RoleCharts),
value = p.RolesCount
}).ToArray();
// var jsonData2 = JsonSerializer.Serialize(chartSortedBar);
// await JS.InvokeVoidAsync("CreateSortedBarFromJson", jsonData2);
await JsSerializerMethodAsync("CreateSortedBarFromJson", chartSortedBar);
}
public async Task GenerateVariableRadiusPieChart()
{
var isActiveCount = await PersonalService.IsActiveStatusCount();
var chartVariableRadiusPie = isActiveCount.Select(p => new
{
status = GetLocalizedIsActiveName(p.ActiveCharts),
value = p.IsActiveCount
}).ToArray();
// var jsonData3 = JsonSerializer.Serialize(chartVariableRadiusPie);
// await JS.InvokeVoidAsync("CreateVariablePieFromJson", jsonData3);
await JsSerializerMethodAsync("CreateVariablePieFromJson", chartVariableRadiusPie);
}
}