Search code examples
asp.net-core.net-coreblazorabp-framework

Why could not my Blazor project consume MyProj.HttpApi.Client correctly?


I used ABP CLI generated a MVC template, with which I would like to try a Blazor Server project. I do add a MyProjBlazorModule which was as same as every common Module, just like the ConsoleTestApp project did:

namespace MyProj.Blazor
{
    [DependsOn(
        typeof(MyProjHttpApiClientModule),
        typeof(AbpHttpClientIdentityModelModule)
        )]
    public class MyProjBlazorModule : AbpModule
    {
    }
}

Then I added the module as service to ConfigureServices method:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSyncfusionBlazor();
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddApplication<TaurusBlazorModule>();

    }

for a rapid test, I also copied ClientDemoService class from template project MyProj.HttpApi.Client.ConsoleTestApp , and I consume it in my index.razor like this:

@inject ClientDemoService _clientService
...
protected override async Task OnInitializedAsync()
{

    await base.OnInitializedAsync();
    profile = await _clientService.RunAsync();
}

But it couldn't work, with a error message in browser:

InvalidOperationException: No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action configureOptions).

while If I copy code identical to the console test project like this:

        using (var application = AbpApplicationFactory.Create<MyProjConsoleApiClientModule>())
        {
            application.Initialize();

            var demo = application.ServiceProvider.GetRequiredService<ClientDemoService>();
            profile = AsyncHelper.RunSync(() => demo.RunAsync());

        }

and it worked. I would like to know the difference between using ABP module and explicitly calling an ugly ServiceProvider method here, and how can I fix this issue in some correct and beautiful way?

Thanks for everyone's help!


Solution

  • Finally, I have got what's wrong with that. In the template source code from abp CLI, the MyProjHttpApiHostModule's ConfigureAuthentication method register authenticate service like this:

        private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAuthentication()
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = configuration["AuthServer:Authority"];
                    options.RequireHttpsMetadata = false;
                    options.ApiName = "MyProj";
                    options.JwtBackChannelHandler = new HttpClientHandler()
                    {
                        ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
                    };
                });
        }
    

    where AddAuthentication() method used empty parameter overload, that caused the No authenticationScheme was specified error. I referenced IdentityServer4 official document and found the right way to do:

    context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(options =>
                {
                    ...
                });
    

    That's easy, I should set the default scheme JwtBearerDefaults.AuthenticationScheme using a different overload of AddAuthentication method just as the error had reported.

    I hope this post could help someone facing the same or similar issue.