Coder Social home page Coder Social logo

blazorextensions / storage Goto Github PK

View Code? Open in Web Editor NEW
226.0 12.0 35.0 575 KB

HTML5 Storage API implementation for Microsoft Blazor

License: MIT License

TypeScript 13.72% JavaScript 3.49% C# 48.66% HTML 34.13%
blazor html5-storage storage webassembly web-assembly

storage's Introduction

Build Package Version NuGet Downloads License

Blazor Extensions

Blazor Extensions are a set of packages with the goal of adding useful things to Blazor.

Blazor Extensions Storage

This package wraps HTML5 Storage APIs. Both Session and Local storage types are supported.

Sample configuration

Setup

The following snippet shows how to setup the storage wrapper by registering it for dependency injection in the Startup.cs of the application.

public void ConfigureServices(IServiceCollection services)
{
    // Add Blazor.Extensions.Storage
    // Both ISessionStorage and ILocalStorage are registered
    services.AddStorage();
}

Usage

The following snippet shows how to consume the storage API in a Blazor component.

@inject ISessionStorage sessionStorage
@inject ILocalStorage localStorage

@functions {
  protected override async Task OnInitAsync()
  {
        var key = "forecasts";
        await sessionStorage.SetItem<WeatherForecast[]>(key, forecasts);
        await localStorage.SetItem<WeatherForecast[]>(key, forecasts);
        var fromSession = await sessionStorage.GetItem<WeatherForecast[]>(key);
        var fromLocal = await localStorage.GetItem<WeatherForecast[]>(key);
  }
}

If you want to consume it outside of a cshtml based component, then you can use the Inject attribute to inject it into the class.

[Inject]
protected ISessionStorage sessionStorage;

[Inject]
protected ILocalStorage localStorage;

public Task LogSomething()
{
        var key = "forecasts";
        await sessionStorage.SetItem<WeatherForecast[]>(key, forecasts);
        await localStorage.SetItem<WeatherForecast[]>(key, forecasts);
        var fromSession = await sessionStorage.GetItem<WeatherForecast[]>(key);
        var fromLocal = await localStorage.GetItem<WeatherForecast[]>(key);
}

Contributions and feedback

Please feel free to use the component, open issues, fix bugs or provide feedback.

Contributors

The following people are the maintainers of the Blazor Extensions projects:

storage's People

Contributors

aesalazar avatar attilah avatar celluj34 avatar danielcarmingham avatar ebekker avatar galvesribeiro avatar kant2002 avatar phanronald avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

storage's Issues

Latest commit (PR 22): Under Netstandard 3.0: Cannot consume scoped service 'Microsoft.JSInterop.IJSRuntime' from singleton 'Blazor.Extensions.Storage.SessionStorage'

Using .net core 3 preview 4 and your latest commit of PR22, injecting LocalStorage into my class using DI results in error:

Cannot consume scoped service 'Microsoft.JSInterop.IJSRuntime' from singleton 'Blazor.Extensions.Storage.LocalStorage'

I believe this is because your StorageExtensions.cs calls:
AddSingleton<LocalStorage>()

But when your LocalStorage.cs constructor injects IJSRuntime public LocalStorage(IJSRuntime Runtime) I am guessing that IJSRuntime is added to the Service Collection as Scoped, therefore consuming it from your Singleton StorageExtensions.cs cases this error.

FYI I have tried amending your StorageExtensions.cs to read: AddScoped<LocalStorage>(). This does compile and run but then any call to await _localStorage.SetItem<>() never returns...

JSException in Blazor 0.8

When using the extension in Blazor 0.8 the follow exception is thrown:

[Microsoft.JSInterop.JSException] Could not find 'BlazorExtensions' in 'window'.

Observable Storage

Is there any plan to provide an observable storage to update the view when the stored item has changed?

Writing of objects to local storage broken in 0.1.6 w/ Blazor 0.7.0

Since upgrading to Blazor 0.6.0 to 0.7.0 and from Storage 0.1.5 to 0.1.6, Writing objects directly to local storage seems broken.

i.e. Doing this:

storage.SetItem($"MyAppName.{nameof(MyClassName).ToLower()}", myClassInstance);

in 0.1.5 resulted in something like { \"Id\": 1337 } being saved to storage, where as in 0.1.6 it only writes [object Object] instead.
Downgrading back to 0.1.5 (but still with Blazor 0.7.0) works as expected.

LocalStorage.GetItem not working and takses all CPU

I have a service class wiht method that looks like this:

        public async Task CreateAsync(string title, string description)
        {
            int id = 1;
            var notes = new List<Note>();
            var notesArray = await _localStorage.GetItem<List<Note>>(key);

            if (notes.Count > 0)
                id += notes.Select(x => x.Id).Max();

            notes.Add(new Note(id, title, description));

            await _localStorage.SetItem<List<Note>>(key, notes);
        }

The line with _localStorage.GetItem<List<Note>>(key); freezes this method and resoults with 100% CPU usage. If I comment this line then it works great (but then I'm not able to do the Get operation).

I am using newest release of the Blazor and this extension.

Doc and official package inconsistency?

I was so confused because the doc state that I should use ILocalStorage but in my package installed from Nuget there is no such thing. I checked the source code and see ILocalStorage is there but have no idea why I can't use it.

Turned out the Nuget official release is still at 1.0.0 (I see there are 2 preview versions now), and there is an update 3 months ago that change it.

I think the README should be updated to say that, if we are still using the official 1.0.0, we should use LocalStorage instead until next version is official released..

Add support for Preview7

Now that Preview7 is out, I am eager to put that version into focus. Preview7 is also production ready.

sessionStorage.SetItem not working

i use await sessionStorage.SetItem("response", response); it throw error

Exception thrown: 'System.InvalidCastException' in System.Private.CoreLib.dll
Exception thrown: 'System.Reflection.TargetInvocationException' in System.Private.CoreLib.dll
Exception thrown: 'System.InvalidCastException' in Microsoft.JSInterop.dll

but await localStorage.SetItem("response", response); is working

ILocalStorage is not available

I have added this nuget to my project and I am unable to use ILocalStorage, it is not available. I have to use LocalStorage directly which causes my app to hang when trying to retrieve values.

MethodAccessException

When I attempt to call the SetItem method of the StorageBase class I get the following exception:

MethodAccessException: Attempt by method 'Cloudcrate.AspNetCore.Blazor.Browser.Storage.StorageBase.SetItem(System.String, System.String)' to access method 'Microsoft.JSInterop.JSRuntime.get_Current()' failed.

with the following stack trace:

System.MethodAccessException: Attempt by method 'Cloudcrate.AspNetCore.Blazor.Browser.Storage.StorageBase.SetItem(System.String, System.String)' to access method 'Microsoft.JSInterop.JSRuntime.get_Current()' failed.
at Cloudcrate.AspNetCore.Blazor.Browser.Storage.StorageBase.SetItem(String key, String data)
at TBS.Shared.NavMenu.OnInitAsync() in --code path--
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.Rendering.Renderer.GetErrorHandledTask(Task taskToHandle)
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitPrerenderer.CircuitHost_UnhandledException(Object sender, UnhandledExceptionEventArgs e)
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.Renderer_UnhandledException(Object sender, Exception e)
at Microsoft.AspNetCore.Components.Browser.Rendering.RemoteRenderer.HandleException(Exception exception)
at Microsoft.AspNetCore.Components.Rendering.Renderer.GetErrorHandledTask(Task taskToHandle)
at Microsoft.AspNetCore.Components.Rendering.Renderer.ProcessAsynchronousWork()
at Microsoft.AspNetCore.Components.Rendering.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterCollection initialParameters)
at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterCollection initialParameters)
at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterCollection initialParameters)
at Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.<>c__DisplayClass41_0.<b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c__111.<<InvokeAsync>b__11_0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Components.Server.Circuits.CircuitPrerenderer.PrerenderComponentAsync(ComponentPrerenderingContext prerenderingContext) at Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperComponentPrerenderingExtensions.RenderComponentAsync[TComponent](IHtmlHelper htmlHelper, Object parameters) at TBS.Pages.Pages__Host.<ExecuteAsync>b__22_1() in C:\Users\Dominick\Desktop\Programming\BlazeTrail\The Build Show\Projects\The Build Show\The Build Show\The Build Show\Pages\_Host.cshtml:line 150 at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync() at TBS.Pages.Pages__Host.ExecuteAsync() at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context) at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts) at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context) at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable1 statusCode)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Extra double-quotes when `SetItem` a string?

Not sure if this is intended, but when I try to use SetItem with a string:

await this.storage.SetItem("jwt", "hello");

The result of Javascript sessionStorage.jwt is "hello" (the double quotes is inside the string, string length is 7).

I guess because it always uses JSON. True that this.storage.GetItem<string>("jwt") returns correct string but it makes us need to be careful when reading from Javascript.

Provide Overload for Keys of Type Guid

It would be nice if you can add the following extension methods to improve the usage.

Usage

await sessionStorage.CreateOrUpdate<SomeStateObject>(notification.Id, state => state.OnNotification(notification));

Instead of

var state = await sessionStorage.GetItem<SomeStateObject>(notification.Id) ?? new new SomeStateObject();
state.OnNotification(notification);
await sessionStorage.SetItem<SomeStateObject>(notification.Id, state);

Extensions

    public static class StorageExtensions
    {
        public static async Task<TState> CreateOrUpdate<TState>(this IStorage storage, Guid id, Action<TState> handler) where TState : class, IState
        {
            var state = await storage.GetItem<TState>($"{id}") ?? Activator.CreateInstance<TState>();

            handler(state);

            await storage.SetItem($"{id}", state);

            return state;
        }

        public static async Task<TState> Update<TState>(this IStorage storage, Guid id, Action<TState> handler) where TState : class, IState
        {
            var state = await storage.GetItem<TState>($"{id}");

            if (state == null)
            {
                throw new InvalidOperationException("State not found!");
            }

            handler(state);

            await storage.SetItem($"{id}", state);

            return state;
        }
    }

Using "Wait" or "Result" in the constructor for an injected class hangs the browser.

When using "Wait" or "Result" in the constructor for a class that uses the LocalStorage object, the browser will hang and eat large amounts of CPU.

To reproduce:

  1. Create a new Blazor WebAssembly project from the official templates.
  2. In the "Pages" folder, create a new file named "Counter.razor.cs"
  3. Copy the following code into that class:
using Blazor.Extensions.Storage;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorApp1.Pages
{
    public partial class Counter
    {
        [Inject]
        public TestService TestService { get; set; }

        protected override async Task OnInitializedAsync()
        {
            var item = await TestService.AsyncMethod();

            await base.OnInitializedAsync();
        }
    }

    public class TestService
    {
        protected LocalStorage _localStorage { get; set; }

        public TestService(LocalStorage localStorage)
        {
            _localStorage = localStorage;

            //string item = AsyncMethod().Result;
        }

        public async Task<string> AsyncMethod()
        {
            return await _localStorage.GetItem<string>("key");
        }
    }
}
  1. Uncomment the line string item = AsyncMethod().Result;, start the app, and navigate to the page.

The "correct" way of doing this is to use the "OnInitializedAsync" override as I have done in the example, but no other Blazor library hangs the browser in this way so I thought I would report it.

Create a server-side sample

I'm able to execute the client-side sample, but when I try to apply the same to a server-side project, it results in errors. Since server-side is the only currently supported method, there should be a sample for it.

Next enhancements

  • Make interfaces for both storages so it can make components testable
  • Make the concrete storage classes to have internal ctors

Extra Double Quotes in Storage Values

Hi all.

I was trying out your extension and it works very well. The one minor issue I ran into was the stored "Value" of a string object is actually wrapped like this: "string_value":

image

But should it not be stored like this:

image

I can confirm that those quotes are not part of the string object. Its not a big deal to simply do:

sessionStorage.getItem(keyName).slice(1, -1)

But just wondering since I have always assumed that they should not be added.

Local Storage does not work in Edge Browser

I am not able to get local storage working in Microsoft Edge browser but does work fine with Chrome. I was able to re-produce this by running the Blazor.Extensions.Storage.Test project first in Chrome to validate it was working, which it was and then in Edge. When you run it in Edge you see the following in the Console output.

image

Could not find 'BlazorExtensions' in 'window' (*Client* mode)

BlazorExtensions/Storage 1.1.0-preview3 issue:

Similar to issue #35 "Could not find 'BlazorExtensions' in 'window' (Server mode)", but client side:

After updating from ASP .NET 3.0 to latest 3.1 Microsoft.AspNetCore.Blazor (3.1.0-preview4.19579.2), I had to change the injection to the related interfaces to compile:

using Blazor.Extensions.Storage;
using Blazor.Extensions.Storage.Interfaces;

The first "using" statement seems not necessary any more.

And injection also changed from the class "SessionStorage" to the new interface style "ISessionStorage":
[Inject] protected ISessionStorage SessionStorage { get; set; }

But after compiling successfully, I also receive the following exception (similar to server side issue):

WASM: Microsoft.JSInterop.JSException: Could not find 'BlazorExtensions' in 'window'. blazor.webassembly.js:1:35158
printErr http://localhost:58811/_framework/blazor.webassembly.js:1
put_char http://localhost:58811/_framework/wasm/mono.js:1
write http://localhost:58811/_framework/wasm/mono.js:1
write http://localhost:58811/_framework/wasm/mono.js:1
doWritev http://localhost:58811/_framework/wasm/mono.js:1
_fd_write http://localhost:58811/_framework/wasm/mono.js:1
http://localhost:58811/_framework/wasm/mono.wasm:400200
http://localhost:58811/_framework/wasm/mono.wasm:403904
http://localhost:58811/_framework/wasm/mono.wasm:17263
http://localhost:58811/_framework/wasm/mono.wasm:190639
http://localhost:58811/_framework/wasm/mono.wasm:739184
http://localhost:58811/_framework/wasm/mono.wasm:148347
http://localhost:58811/_framework/wasm/mono.wasm:500900
http://localhost:58811/_framework/wasm/mono.wasm:501148
http://localhost:58811/_framework/wasm/mono.wasm:330473
http://localhost:58811/_framework/wasm/mono.wasm:477291
http://localhost:58811/_framework/wasm/mono.wasm:893930
http://localhost:58811/_framework/wasm/mono.wasm:895281
http://localhost:58811/_framework/wasm/mono.wasm:751234
_mono_background_exec http://localhost:58811/_framework/wasm/mono.js:1
pump_message http://localhost:58811/_framework/wasm/mono.js:1

What is the reasons for this? It seems as if the client side can not access the BlazorExtensions out of the box any more (which worked fine using .NET Core 3.0 and Blazor.Extensions.Storage 1.0).

GetItem<T> never returns with ValueTypes

Hello, quick example here:

      try {
        var result = await Get<string>("key_that_not_exists");
        Logger.LogInformation("result is null: " + result);

        // Or DateTime for example
        var result2 = await Get<SomeStruct>("key_that_not_exists");
        Logger.LogInformation("will never print: " + result2);
      } catch (Exception e) {
        Logger.LogError(e, "this will never happen");
      }

Calling LocalStorage.GetItem<> when an item does not exist stalls and results in high CPU usage.

I have the following code which is called from a component. If the item is not yet stored in LocalStorage, the component never loads, resulting in the page never loading and the CPU usage of the tab skyrocketing. Eventually Chrome/Firefox prompts to kill the tab.

const string TOKEN = "token";
private readonly LocalStorage _localStorage;

public async Task<bool> IsLoggedIn()
{
    var token = await _localStorage.GetItem<string>(TOKEN);
    return !string.IsNullOrWhiteSpace(token);
}

The code above gets called in the component like this:

@if (IsLoggedIn)
{
    // Some HTML
}
else
{
    // Some other HTML
}

@functions {
    bool IsLoggedIn
    {
        get
        {
            AuthService.IsLoggedIn().Result;
        }
    }
}

Issue with Edge - QuotaExceededError

"WASM: Microsoft.JSInterop.JSException: QuotaExceededError"

The object being written to storage is 16-30k. Works fine in Chrome and FF. Haven't had a chance to test on mobile devices. But fully patching Windows 10 with Edge 44.18362.329.0 I get the following.

image

Expose the `length` property and iterator on storage interfaces

Shouldn't the length and natural JS iterators of the storage interfaces be exposed to make the interfaces more useful?

Currently the interfaces give you the basic read/write access, but you have to know all the keys you want to work with in advance. There is the Key(int) method that returns the key at a given index, but the user needs to know in advance what the length is.

By exposing a length property of the storage items, the item keys can be safely iterated, and by exposing the iterator, the keys themselves can be enumerated directly.

Installing this in an 0.9.0 app causes the app to break.

Because of the fixed reference to Blazor 0.7.0 when you try to use this in a newer 0.9.0 app from Visual Studio 2019 it causes a conflict due to the installation of the Blazor Browser run-time 0.7.0

Basically you'll see this:
image

as soon as you accept the license.

And your Program.cs will show as this:
image

Cheers
Shawty

_content js files not being loaded correctly leading to JSInterop errors

Hi

I am attempting to load js files from an external component package (mudblazor) . The web app is initialized from a calling application, a console application.

Framework: netcoreapp3.1

_Host.cshtml

<script src="_framework/blazor.server.js" autostart="true"></script>
<script src="_content/mudblazor/mudblazor.min.js"></script>

I discovered some issues related to the .StaticWebAssets.xml not being copied when the main project was built or run using F5. A post-build step now always copies this file.

I discovered that I needed to add this to the CreateHostBuilder method in the Program file

webBuilder.ConfigureAppConfiguration((ctx, cb) =>
{
if (!ctx.HostingEnvironment.IsDevelopment()){
StaticWebAssetsLoader.UseStaticWebAssets(
ctx.HostingEnvironment,
ctx.Configuration);
}
});
With these changes it all works fine, both in debug and release

One item I can't understand is that the StaticWebAssets.xml links back to the install directory of the nuget package. I tried various different ways of linking to the js file (MudBlazor.min.js) which I set to be copied as both content and an embedded resource. However no other method of loading the file worked as it resulted in a JSInterop error

Microsoft.JSInterop.JSException: Could not find 'domService' in 'window'.
Error: Could not find 'domService' in 'window'.
at http://localhost:5006/_framework/blazor.server.js:8:35211
at Array.forEach ()
at p (http://localhost:5006/_framework/blazor.server.js:8:35171)
at http://localhost:5006/_framework/blazor.server.js:8:35881
at new Promise ()
at e.beginInvokeJSFromDotNet (http://localhost:5006/_framework/blazor.server.js:8:35854)
at http://localhost:5006/_framework/blazor.server.js:1:20247
at Array.forEach ()
at e.invokeClientMethod (http://localhost:5006/_framework/blazor.server.js:1:20217)
at e.processIncomingData (http://localhost:5006/_framework/blazor.server.js:1:18028)
at Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation[T](String identifier, Object[] args)
at MudBlazor.MudDrawer.UpdateHeight()
at MudBlazor.MudDrawer.OnAfterRenderAsync(Boolean firstRender)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Error: Unhandled exception in circuit 'ZwuqTd7cgtzxRSfhWvHSMqEazFgFlRSPmKJ1lzNwXBY'.

So it appears the only way is to link using the StaticWebAssets file.

This works on a local machine however it would appear that for deployments the staticassets folder from the nuget install folder needs to be distributed and the StaticWebAssets.xml file updated to point at the deployed folder

This does not seem correct. It is a workaround and sustainable moving forward.

What am I missing? Any pointers would be gratefully accepted.

Thanks in advance
Kieran

Could not find 'BlazorExtensions' in 'window' (Server mode)

In a new project, using server side template, I added the reference to BlazorExtensions storage (0.2.1), added the services.AddStorage() line to register the services. If I modify the counter example to this:

`@page "/counter"
@using Blazor.Extensions.Storage
@Inject SessionStorage sessionStorage
@Inject LocalStorage localStorage

Counter

Current count: @currentCount

<button class="btn btn-primary" @OnClick="IncrementCount">Click me

@code {
int currentCount = 0;

async void IncrementCount()
{
    currentCount=await localStorage.GetItem<int>("counter");
    currentCount++;
    localStorage.SetItem("counter", currentCount).Wait();
}

}
`
I receive the error Could not find 'BlazorExtensions' in 'window'.
blazor.server.js is present in Sources when I enter in dev mode in chrome.
dotnet --version outputs 3.0.100-preview7-012821.

Is that correct?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.