1

I'm trying to write an .NET MAUI Blazor application, that shares the UI with a traditional Blazor application, as can be seen in the BlazorWeather example found at https://github.com/danroth27/BlazorWeather.

My twist on this formula is that I want to be able to use authentication within my application and share as much code as posible. Ideally I'd want to put all aplication logic inside the shared UI (and API that's of course also going to be just one for both Web and MAUI).

I've tried to create a very basic sample Solution so you could see what my issue is. The public repository should be accessible at https://github.com/Dukenware/OneToRuleThemAll

The steps I've followed:

  1. I've started by creating a Blazor Server with default authentication of type "Individual Accounts".
  2. Tested that the application runs as expected.
  3. Created a Razor Class Library project that I've added to the solution.
  4. Moved all logic from BlazorServer to the RazorClassLibrary project.
  5. Fixed HTML styling and so on so the application runs as before.
  6. Added MAUI Blazor project.
  7. Tested that the MAUI application runs as expected.
  8. Referenced the RazorClassLibraryProject.
  9. Tried displaying the UI from RazorClassLibrary by running the RazorClassLibrary.App from MauiBlazor's Main.razor.
  10. Getting the authentication exception:
GetAuthenticationStateAsync was called before SetAuthenticationState.
   at Microsoft.AspNetCore.Components.Server.ServerAuthenticationStateProvider.GetAuthenticationStateAsync()
   at Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState.OnInitialized()
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()

I'd really appretiate if someone could point me to a working templete that I could use to build my application upon. Any feedback is heartily welcome.

Duken.Jr
  • 86
  • 5

1 Answers1

1

I also ran into this issue.

Here is what I found. I was getting that error when my AuthenticationState was not returning the correct result. This is an implementation of a CustomAuthenticationStateProvider implementing the default AuthenticationStateProvider :

public class CustomAuthenticationStateProvider :AuthenticationStateProvider
{

    public async Task Login(string token)
    {
        await SecureStorage.SetAsync("accounttoken", token);
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }

    public async Task Logout()
    {
        SecureStorage.Remove("accounttoken");
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }

    public override async Task<AuthenticationState>GetAuthenticationStateAsync()
    {

        try
        {
            var userInfo = await SecureStorage.GetAsync("accounttoken");
            if (userInfo != null)
            {
                var claims = new[] { new Claim(ClaimTypes.Name, "User") };
                var identity = new ClaimsIdentity(claims, "Server authentication");
                return new AuthenticationState(new ClaimsPrincipal(identity));
            }
        }
        catch (HttpRequestException ex)
        {
            //This should be implemented better
            Console.WriteLine("Request failed:" + ex.ToString());
        }

        return new AuthenticationState(new ClaimsPrincipal());
     }
}

Then in my MauiProgram I added:

builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();

I was returning null instead of

new AuthenticationState(new ClaimsPrincipal());

Which was causing the same error :

GetAuthenticationStateAsync was called before SetAuthenticationState.
at Microsoft.AspNetCore.Components.Server.ServerAuthenticationStateProvider.GetAuthenticationStateAsync()
at Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState.OnInitialized()
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()

Hope this helps!

Mentyy
  • 11
  • 1
  • 7
  • I'm gonna try that as soon as my current schedule allows. If you'd be willing to put up a working template on github, something similar to my original listing here, that'd also be much appretiated. Thank you for all your help – Duken.Jr Jun 17 '22 at 19:51