I am trying to use the localStorageService
in my CustomAuthStateProvider
class so I can create a AuthenticationState
based on a key in local storage (just to learn and to practice).
However, when I run my application, I get an error telling me that no suitable constructor can be found for CustomAuthStateProvider
. The error makes sense but I don't understand how I can fix it and haven't found much online.
Here is the error:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: A suitable constructor for type 'BlazorBattles.Client.CustomAuthStateProvider' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
System.InvalidOperationException: A suitable constructor for type 'BlazorBattles.Client.CustomAuthStateProvider' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
Here is my CustomAuthStateProvider
implementing AuthenticationStateProvider
:
public class CustomAuthStateProvider : AuthenticationStateProvider
{
private readonly ILocalStorageService _localStorageService;
CustomAuthStateProvider(ILocalStorageService localStorageService)
{
_localStorageService = localStorageService;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (await _localStorageService.GetItemAsync<bool>("isAuthenticated"))
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "Thomas")
}, "Test Authentication");
ClaimsPrincipal user = new ClaimsPrincipal(claimsIdentity);
AuthenticationState state = new AuthenticationState(user);
//Tell all the components that the Auth state has changed
NotifyAuthenticationStateChanged(Task.FromResult(state));
return (state);
}
//This will result in an unauthorised user because it does not have a claims identity
return (new AuthenticationState(new ClaimsPrincipal()));
}
}
Here is my Program.cs
using BlazorBattles.Client;
using BlazorBattles.Client.Services;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Blazored.Toast;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddBlazoredToast();
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<IBananaService, BananaService>();
builder.Services.AddScoped<IUnitService, UnitService>();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();
await builder.Build().RunAsync();
I am using V4.3.0 for Blazored.LocalStorage and V6 for Microsoft.AspNetCore.Components.Authorization
Thanks.
It works as expected when I remove the constructor and references to LocalStorage but when I try to inject LocalStorage to use it then I get the error. I'm not sure how to make use of the constrctor correctly in this specific case?
Update: The solution to my problem here is to add the public keyword for the constructor
The issue with my code above is that I had missed out the public keyword in my constructor and now it works as expected. A huge thank you to everyone who commented on my post and provided potential solutions, I appreciate the time you took to help me out!
Original code:
CustomAuthStateProvider(ILocalStorageService localStorageService)
{
_localStorageService = localStorageService;
}
Updated code:
public CustomAuthStateProvider(ILocalStorageService localStorageService)
{
_localStorageService = localStorageService;
}