Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application State in BlazorApp .Net 8 #53061

Closed
1 task done
vconfrence opened this issue Dec 29, 2023 · 20 comments
Closed
1 task done

Application State in BlazorApp .Net 8 #53061

vconfrence opened this issue Dec 29, 2023 · 20 comments
Labels
area-blazor Includes: Blazor, Razor Components ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. Status: Resolved

Comments

@vconfrence
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

using cascading values and local storage for application state doesn't seem to work in blazor web app .net 8
cc: @guardrex dotnet/AspNetCore.Docs#31316

Expected Behavior

LocalStorage, renderfragment element of the cascadingAppState component seem to be null.

Steps To Reproduce

https://github.com/vconfrence/BlazorApp1.git

Exceptions (if any)

No response

.NET Version

8

Anything else?

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Dec 29, 2023
@guardrex
Copy link
Contributor

Thanks @vconfrence ... I'll keep an 👁️ on this. If there's doc work to do, we'll hear on this issue after you chat with the PU about your problem. Note that most folks are on holiday 🎆 vacation, so it could take a short while for this issue to be reached.

@javiercn
Copy link
Member

javiercn commented Jan 2, 2024

@vconfrence thanks for contacting us.

Your repro doesn't have any code other than the initial template.

@javiercn javiercn added the Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. label Jan 2, 2024
@ghost
Copy link

ghost commented Jan 2, 2024

Hi @vconfrence. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@vconfrence
Copy link
Author

Inside the counter page the button click triggers a call to the set property of the CascadingAppState which shows the LocalStorageService, ChildContent to be NULL and throws an exception when StateHasChanged() gets called.

Here's what's embedded in the counter page

@page "/counter"

Counter

Counter

Current count: @currentCount

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

@code {
[CascadingParameter] public BlazorApp1.Client.Components.CascadingAppState AppState { get; set; }
private int currentCount = 0;

private void IncrementCount()
{
    //var json = System.Text.Json.JsonSerializer.Serialize(appstate);
    AppState.SetProperty(this, "IsDevelopment", true, false);
    currentCount++;
}

}

@ghost ghost added Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. and removed Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. labels Jan 2, 2024
@guardrex
Copy link
Contributor

guardrex commented Jan 2, 2024

@vconfrence ... To place code in an issue comment use triple-backticks with a code language on a line above the code (```razor) and triple-backticks on a line below (```). It will format the code if you do that ☝️.

@vconfrence
Copy link
Author

Any suggestion to the stated issue would be greatly appreciated.

@vconfrence
Copy link
Author

Hi everyone. any suggestions/comments regarding the described issue?

@SteveSandersonMS
Copy link
Member

@vconfrence I think there's some confusion between DI services and cascading values. These are two separate concepts. Just because you've registered a cascading value of type CascadingAppState does not mean there is any DI service of that type.

You can register and consume that type as a cascading value if you want, but then you're not using DI, and hence the system isn't going to resolve other dependencies like @inject ILocalStorageService LocalStorageService for you.

Alternatively, and more simply, I'd recommend changing CascadingAppState to be a regular DI service (not a Blazor component) and registering it in DI. Then you can @inject it into your other Blazor components, and all its DI dependencies will be resolved by the system.

@SteveSandersonMS SteveSandersonMS closed this as not planned Won't fix, can't repro, duplicate, stale Jan 17, 2024
@SteveSandersonMS SteveSandersonMS added the ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. label Jan 17, 2024
@ghost ghost added the Status: Resolved label Jan 17, 2024
@guardrex
Copy link
Contributor

guardrex commented Jan 17, 2024

@SteveSandersonMS ... We seem to be using a similar approach in one of the examples. I'm not sure how @vconfrence's approach is different from it conceptually. I thought ILocalStorageService was registered by the Blazory service/package in the repro app and that it would be consumed if the registered cascading value is a component.

Our approach that seems quite similar is described at Factor out the state preservation to a common location ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-8.0&pivots=server#factor-out-the-state-preservation-to-a-common-location

@SteveSandersonMS
Copy link
Member

consumed if the registered cascading value is a component

In general you can't resolve a Blazor component from the DI system, at least not if you also want its @inject properties to be populated. Blazor components are normally only constructed during rendering, by the rendering system, which knows about @inject. Additionally, the way the code is structured in the repro above, it's not even resolving the component from the DI system at all - the cascading value is given as a fixed instance that was manually constructed. So there are multiple reasons why it would not have its @inject properties populated.

@guardrex
Copy link
Contributor

Ok, but I thought that @vconfrence orginally tried to wrap the Router with the CascadingAppState component, which is like our example and seems like it would construct the component via rendering. It looks like it was originally attempted here ...

https://github.com/vconfrence/BlazorApp1/blob/master/BlazorApp1/BlazorApp1/Components/Routes.razor

... and then it looks like it was failing for @vconfrence that way, so then @vconfrence tried the root-level registration approach.

Of course, I defer to @vconfrence to say if that's what happened.

@SteveSandersonMS
Copy link
Member

Yes, if it was done as follows, it should work:

<CascadingAppState>
  <Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Client._Imports).Assembly }">
      <Found Context="routeData">
          <RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
          <FocusOnNavigate RouteData="@routeData" Selector="h1" />
      </Found>
  </Router>
</CascadingAppState>

That's a common pattern. Not sure what wasn't working before if this was attempted.

@guardrex
Copy link
Contributor

guardrex commented Jan 17, 2024

Cool ... we're almost there on coverage. I have some draft text just about ready to get this covered.

@vconfrence ... Can you let us know what happened when you tried that ☝️? ... did it 💥 on you?

UpDaTe: I'm working on it here ... Cascading values updates. I'll probably merge it tomorrow, and I'll keep an 👂 open here for further discussion.

@vconfrence
Copy link
Author

We have tried the suggested approach and was facing the same issue. We also tried adding builder.Services.AddCascadingValue in the program.cs and still the same issue.

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Jan 18, 2024

If you provide a repro that shows how you were trying to use <CascadingValue>, I can let you know what's going on.

We also tried adding builder.Services.AddCascadingValue in the program.cs and still the same issue.

I hope I already clarified why calling AddCascadingValue with an instance of CascadingAppState does not cause its @inject properties to be populated.

@vconfrence
Copy link
Author

@vconfrence
Copy link
Author

Here's a repo following the approach discussed.

@vconfrence
Copy link
Author

Any comments/feedback would be greatly appreciated.

@SteveSandersonMS
Copy link
Member

@vconfrence I'm afraid there's a lot of code in the repo you posted, so it's hard to know how much of this relates to the framework and how much of it is potentially an issue in your own code.

If you can reduce it down to a minimal repro (as in, does not contain any code that could be avoided while still showing the issue) we can have a look.

@vconfrence
Copy link
Author

There isn't much code in the application actually. you can ignore all the data objects in the data library which never get used or called. Really appreciate it if someone can look into the super simple example and provide comments or update the solution with comments to make the app state function in blazor web app. This paradigm works perfectly in blazor webassembly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. Status: Resolved
Projects
None yet
Development

No branches or pull requests

4 participants