Accessing Local Storage inside `DelegatingHandler` in Blazor Server and .NET MAUI Blazor
See original GitHub issueWe need to access local storage to get the access token stored in local storage and bind it to the HTTP request but currently accessing local storage inside DelegatingHandler
does not work in Blazor Server and .NET MAUI Blazor.
Here is the DelegatingHandler:
public class AuthorizationDelegatingHandler : DelegatingHandler
{
private readonly ILocalStorageService _localStorage;
public AuthorizationDelegatingHandler(ILocalStorageService localStorage)
{
_localStorage = localStorage;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
try
{
// Here exception is thrown.
LoggedInUserInfo loggedInUserInfo = await _localStorage.GetItemAsync<LoggedInUserInfo>(LocalStorageKey.LoggedInUserInfo);
if (loggedInUserInfo != null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", loggedInUserInfo.AccessToken);
}
}
catch (Exception exception)
{
Console.WriteLine("LocalStorageSerivce throws exception.");
Console.WriteLine(exception);
}
HttpResponseMessage httpResponseMessage = await base.SendAsync(request, cancellationToken);
return httpResponseMessage;
}
}
It throws the following exception for Blazor Server:
System.InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
at Microsoft.AspNetCore.Components.Server.Circuits.RemoteJSRuntime.BeginInvokeJS(Int64 asyncHandle, String identifier, String argsJson, JSCallResultType resultType, Int64 targetInstanceId) in Microsoft.AspNetCore.Components.Server.dll:token 0x60002a4+0x25
at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, CancellationToken cancellationToken, Object[] args) in Microsoft.JSInterop.dll:token 0x600003a+0xda
at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](String identifier, CancellationToken cancellationToken, Object[] args) in Microsoft.JSInterop.dll:token 0x6000038+0x0
at Microsoft.JSInterop.JSRuntimeExtensions.InvokeAsync[TValue](IJSRuntime jsRuntime, String identifier, CancellationToken cancellationToken, Object[] args) in Microsoft.JSInterop.dll:token 0x6000048+0xe
at Blazored.LocalStorage.BrowserStorageProvider.GetItemAsync(String key, Nullable`1 cancellationToken) in D:\GitHub\LocalStorage\src\Blazored.LocalStorage\BrowserStorageProvider.cs:line 23
at Blazored.LocalStorage.LocalStorageService.GetItemAsync[T](String key, Nullable`1 cancellationToken) in D:\GitHub\LocalStorage\src\Blazored.LocalStorage\LocalStorageService.cs:line 59
at MauiBlazor.Shared.Common.AuthorizationDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\GitHub\LocalStorage\samples\MauiBlazor.Shared\Common\AuthorizationDelegatingHandler.cs:line 31
and trows following exception for .NET MAUI Blazor:
System.NullReferenceException: Object reference not set to an instance of an object.
[DOTNET] at Microsoft.AspNetCore.Components.WebView.Services.WebViewJSRuntime.BeginInvokeJS(Int64 taskId, String identifier, String argsJson, JSCallResultType resultType, Int64
[DOTNET] targetInstanceId) in Microsoft.AspNetCore.Components.WebView.dll:token 0x6000113+0x0
[DOTNET] at Microsoft.JSInterop.JSRuntime.InvokeAsync[String](Int64 targetInstanceId, String identifier, CancellationToken cancellationToken, Object[] args) in Microsoft.JSInter
[DOTNET] op.dll:token 0x600003a+0x10a
[DOTNET] at Microsoft.JSInterop.JSRuntime.InvokeAsync[String](String identifier, CancellationToken cancellationToken, Object[] args) in Microsoft.JSInterop.dll:token 0x6000038+0x0
[DOTNET] at Microsoft.JSInterop.JSRuntimeExtensions.InvokeA
[DOTNET] sync[String](IJSRuntime jsRuntime, String identifier, CancellationToken cancellationToken, Object[] args) in Microsoft.JSInterop.dll:token 0x6000048+0xe
[DOTNET] at Microsoft.JSInterop.JSRuntimeExtens07-16 00:29:47.884 I/DOTNET (24839): at Blazored.LocalStorage.BrowserStorageProvider.GetItemAsync(String key, Nullable`1 cancellationToke
[DOTNET] n) in Blazored.LocalStorage.dll:token 0x6000005+0x24
[DOTNET] at Blazored.LocalStorage.LocalStorageService.<GetItemAsync>d__5`1[[MauiBlazor.Shared.Models.IdentityModels.LoggedInUserInfo, MauiBlazor.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
[DOTNET] MoveNext() in Blazored.LocalStorage.dll:token 0x6000082+0x29
[DOTNET] at MauiBlazor.Shared.Extensions.LocalStorageServiceExtensions.GetUserInfoAsync(ILocalStorageService localStorage) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Extensions\Loc
[DOTNET] alStorageServiceExtensions.cs:line 19
[DOTNET] at MauiBlazor.Shared.Common.AuthorizationDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Common\Authorizat
[DOTNET] ionDelegatingHandler.cs:line 30
[DOTNET] at System.Net.Http.Ht
[DOTNET] tpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) in System.Net.Http
[DOTNET] at MauiBlazor.Shared.Services.UserService.LoginAsync(LoginModel loginModel) in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazor.Shared\Services\UserService.cs:line 128
[DOTNET] at MauiBlazorApp.Components.IdentityComponents.Log
[DOTNET] inComponent.HandleValidSubmitAsync() in D:\GitHub\CleanArchitecture\src\ClientApps\MauiBlazorApp\MauiBlazorApp\Components\IdentityComponents\LoginComponent.razor.cs:line 51
Is there any workaround so that we can access local storage inside DelegatingHandler
?
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:12 (3 by maintainers)
Top Results From Across the Web
How do I access browser local storage in Blazor?
LocalStorage package can be used to access the browser's local storage in Blazor. For this you need to install the package and add...
Read more >Blazored
When creating a Blazor application with a reference to Blazor.LocalStorage, the assemblies that are downloaded as part of the application seems to include...
Read more >Connect to local web services from Android emulators and ...
Learn how a .NET MAUI app running in the Android emulator or iOS simulator can consume a ASP.NET Core web service running locally....
Read more >How to display local image as well as resources ...
Net MAUI Blazor I can use an img tag to display an image from wwwroot folder. But how to display an image from...
Read more >Authentication with client-side Blazor using WebAPI and ...
In this post, I show how you can build a client-side Blazor app with authentication using WebAPI and ASP.NET Core Identity.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@mkArtakMSFT Thank you for your patience. Here is the Minimal Repo (https://github.com/TanvirArjel/LocalStorageInsideDL). To reproduce the error, just run the app and click on the
Products
menu.@TanvirArjel it seems that you are using a custom container library, is that the case?
The Blazor server case is clear and by design. You can’t use JS interop during prerendering.
On the Maui case, it seems to be that there is a miss-configuration in your DI container lifetimes somewhere that it is causing you to receive a new instance of the IJSRuntime instead of the instance Blazor creates.