Blazor WebAssembly Hosted Pre-Render Exception : Cannot provide a value for property 'AuthenticationStateProvider'

48 Views Asked by At

I have a blazor webassembly hosted solution that is using identity for authentication. Recently I realized that pre-render is not working correctly as the very first load of my website shows only the "loading" in the network preview and not the pages html.

I went through and verified that my application is set up for pre-render, however, now I keep getting the following error on the sites launch

"InvalidOperationException: Cannot provide a value for property 'AuthenticationStateProvider' on type 'Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState'. There is no registered service of type 'Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider'."

I have searched on here and the only answer is make sure the clients Program.cs has the following added:

builder.Services.AddAuthorizationCore();

builder.Services.AddApiAuthorization()
    .AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();

Well mine does and I am still running into these issues. Can someone help point me in the right direction

Server - Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    //Register the Datacontext and Connection String
    services.AddDbContext<DataContext>(options =>
        options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
        .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
    );

    services.AddDatabaseDeveloperPageExceptionFilter();

    //Sets up the default Asp.net core Identity Screens - Use Identity Scaffolding to override defaults
    services.AddDefaultIdentity<ApplicationUser>( options =>
            {
                ***OMITED***
            })
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<DataContext>();

    //Associates the User to Context with Identity
    services.AddIdentityServer().AddApiAuthorization<ApplicationUser, DataContext>( options =>
    {
        options.IdentityResources["openid"].UserClaims.Add(JwtClaimTypes.Role);
        options.ApiResources.Single().UserClaims.Add(JwtClaimTypes.Role);
    });
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove(JwtClaimTypes.Role);

    //Adds authentication handler
    services.AddAuthentication().AddIdentityServerJwt();

    services.AddCors(options =>
    {
        options.AddDefaultPolicy(
            policy =>
            {
                policy.WithOrigins("https://www.siteName.com",
                    "https://siteName.com",
                    "https://siteName.azurewebsites.net",
                    "https://localhost:44395"
                    );
            });
    });

    services.AddHttpContextAccessor();

    services.AddControllersWithViews();
    services.AddRazorPages();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
        app.UseWebAssemblyDebugging();
    }
    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();
    }

    //AutoMigrates data
    dataContext.Database.Migrate();

    app.UseHttpsRedirection();
    app.UseBlazorFrameworkFiles();
    app.UseStaticFiles();

    app.UseSerilogIngestion();
    app.UseSerilogRequestLogging();

    app.UseRouting();

    app.UseIdentityServer();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapControllers();
        endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
        //endpoints.MapFallbackToFile("index.html");
        endpoints.MapFallbackToPage("/_Host");
    });
}

Server - Pages/_Host.cshtml

@page
@using Microsoft.AspNetCore.Components.Web;
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers


<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" />

    <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />

  
    <base href="/" />
    <script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
</script>

    
</head>

<body>
    <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="_content/Blazor-Analytics/blazor-analytics.js"></script>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" crossorigin="anonymous"></script>
    

</body>

</html>

Client - Program.cs

public class Program
{
    public static async Task Main(string[] args)
    {
        //Serilog 
        var levelSwitch = new LoggingLevelSwitch();
        Serilog.Log.Logger = new LoggerConfiguration()
            .MinimumLevel.ControlledBy(levelSwitch)
            .Enrich.WithProperty("InstanceId", Guid.NewGuid())
            .Enrich.FromLogContext()
            .WriteTo.BrowserHttp(controlLevelSwitch: levelSwitch)
            .CreateLogger();

        Serilog.Log.ForContext<Program>().Information("Client has started");

        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        //builder.RootComponents.Add<App>("#app");

        builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

        builder.Services.AddAuthorizationCore();

        builder.Services.AddApiAuthorization()
            .AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();

        builder.Services.AddLogging(logging =>
       {
           logging.ClearProviders();
           logging.AddSerilog(dispose: true);
       });

        var baseAddress = new Uri($"{builder.HostEnvironment.BaseAddress}api/");

        builder.Services.AddHttpClient("ApplicationName.ServerAPI", client => client.BaseAddress = baseAddress)
            .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

        //Add Public Client
        builder.Services.AddHttpClient<PublicClient>(client => client.BaseAddress = baseAddress);

        // Supply HttpClient instances that include access tokens when making requests to the server project
        builder.Services.AddScoped(sp =>
            sp.GetRequiredService<IHttpClientFactory>()
            .CreateClient("BBQFriend.ServerAPI"));
                   

        builder.RootComponents.Add<HeadOutlet>("head::after");

       

        await builder.Build().RunAsync();
    }
}
0

There are 0 best solutions below