1
votes

I'm new to Blazor, but I have a component which is routable. It calls an api endpoint which allows anonymous. From my understanding, Blaozr WASM automatically attaches the tokens in the headers to each http request, therefore, in my Blazor WASM HttpService, I have two httpClient setups, one for anonymous, one http which calls the tokens.

Going to the route as a logged in user works fine, going to the route without being logged in produces the error below, but I'm not sure why. Also, I've tried to place breakpoints at all relevant sections (http service, component class) and none of the breakpoints get hit. I put a breakpoint at user.Identity.isAuthenticated in the component and it still doesn't get hit. The page just loads with that error in the console. Any guidance? I'm not sure how I can effectively debug this if breakpoints refuse to be honored, lol.

Program.CS has:

builder.Services.AddHttpClient("Quillerz.AnonAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
              .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddHttpClient("Quillerz.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
                .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

Component code:

@page "/communities/{CommunityId:guid}"
@using Quillerz.Shared.Communities
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject Quillerz.Client.Services.ICommunityHttpService CommunityService
@inject NavigationManager Navigation
@inject NotificationService NotificationService


@if (Community != null)
{
    <div class="container">
        <div class="row">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <div class="d-flex w-100 justify-content-between">
                            <h5 class="card-title">@Community.Name</h5>
                            <span class="text-muted">@Community.MemberCount members</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
}
else
{
    <span>Couldn't find community.</span>
}

@code {
    [Parameter]
    public Guid CommunityId { get; set; }

    private CommunityDto Community { get; set; } = new CommunityDto();

    protected override async Task OnInitializedAsync()
    {
        if (!string.IsNullOrEmpty(CommunityId.ToString()))
        {
            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            var user = authState.User;

            if (user.Identity.IsAuthenticated)
            {
                Community = await CommunityService.GetCommunity(CommunityId, true);
            }
            else
            {
                Community = await CommunityService.GetCommunity(CommunityId, false);
            }
        }
        else
        {
            NotificationMessage errMsg = new NotificationMessage()
            {
                Severity = NotificationSeverity.Error,
                Summary = "Whoops!",
                Detail = "Couldn't find the community id.",
                Duration = 4000
            };
            NotificationService.Notify(errMsg);
        }
    }
}

HttpService:

private readonly HttpClient httpClient;
private readonly IHttpClientFactory httpClientFactory;
private readonly HttpClient anonHttp;

public CommunityHttpService(HttpClient httpClient, IHttpClientFactory httpClientFactory)
{
    if (httpClient == null) throw new ArgumentNullException("Http is null.");
    this.httpClient = httpClient;
    this.httpClientFactory = httpClientFactory;

    anonHttp = httpClientFactory.CreateClient("Quillerz.AnonAPI");
}

public async Task<CommunityDto> GetCommunity(Guid communityId, bool userIsAuthenticated)
{
    if (!userIsAuthenticated)
    {
       return await anonHttp.GetFromJsonAsync<CommunityDto>($"api/communities/" + communityId);
    }
    else
    {
       return await httpClient.GetFromJsonAsync<CommunityDto>($"api/communities/" + 
          communityId);
    }
}

full error in console:

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: ''
Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessTokenNotAvailableException: ''
   at Microsoft.AspNetCore.Components.WebAssembly.Authentication.AuthorizationMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
   at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__9`1[[Quillerz.Shared.Communities.CommunityDto, Quillerz.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at Quillerz.Client.Services.CommunityHttpService.GetCommunity(Guid communityId, Boolean userIsAuthenticated) in C:\Code\Quillerz\Quillerz\Quillerz\Client\Services\CommunityHttpService.cs:line 45
   at Quillerz.Client.Pages.CommunityDetail.OnInitializedAsync() in C:\Code\Quillerz\Quillerz\Quillerz\Client\Pages\CommunityDetail.razor:line 51
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
1

1 Answers

0
votes

A little late but I had the same issue in my Blazor WASM with authentication. In my case I needed to protect my razor component like: @attribute [Authorize(Roles="admin")]. After this it worked fine.