【问题标题】:Share Data Through Service in ASP.NET Blazor (Client Side)通过 ASP.NET Blazor 中的服务共享数据(客户端)
【发布时间】:2020-01-27 10:28:56
【问题描述】:

我曾经在 MVC Application 中有一个公共服务,将其注册为 Transient 服务并在整个应用程序中访问它的值而没有任何问题。

我尝试在客户端 Blazor 应用程序中实现相同的机制

首先创建了一个类AppState

public class AppState
{
    public string BaseUrl { get; set; }
}

注册为服务

services.AddSingleton<AppState, AppState>();

用于 Blazor 组件索引组件

public class IndexComponent : ComponentBase
{
    [Inject]
    HttpClient Http { get; set; }

    [Inject]
    public AppState AppState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        AppState = await Http.GetJsonAsync<AppState>(ConfigFiles.GetPath("appsettings.json"));
        await Task.FromResult(0);
    }
}

试图在 index.razor 文件中打印 base url

@page "/"
@inherits IndexComponent

<p>@AppState.BaseUrl</p>

到这里为止很好,现在因为它包含基本 url,所以我想在另一个组件中访问它

public class MiniCartComponent : ComponentBase
{
    [Inject]
    public AppState AppState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await Task.FromResult(0);
    }
}

这里是空的,我不知道为什么

我尝试在剃须刀文件中打印它

@inherits MiniCartComponent
<p>@AppState.BaseUrl</p>

这里是空的,它被注册为跨组件共享数据的服务,一旦设置它不应该在整个应用程序中具有价值吗??

【问题讨论】:

  • AppState = await Http.GetJsonAsync(ConfigFiles.GetPath("appsettings.json")); 更改为 var appState = await Http.GetJsonAsync(ConfigFiles.GetPath("appsettings.json")); AppState.BaseUrl = appState.BaseUrl;
  • 好吧,它成功了,它背后的概念是什么。以后json文件里会有很多key,我得这样一一设置
  • 只修改AppState,不要设置其他值。如果有很多字段,只需将其包装到其他类。
  • 好的,但是在 AppState.BaseUrl = appState.BaseUrl; 之后它是如何工作的,你能澄清一下吗
  • 您将 AppState 注册为单例,我将其称为实例 A,当您将其注入组件时,它仍然是实例 A,并且您在组件中使用 API 的结果设置 AppState,它将是实例 B,对实例 A。

标签: .net-core blazor blazor-server-side .net-core-3.0 blazor-client-side


【解决方案1】:

首先注册一个单例实例

services.AddSingleton<AppState, AppState>();

这对我来说有点奇怪。恕我直言,应该是

services.AddSingleton<IAppState, AppState>();

services.AddSingleton<AppState>();

但这不是问题。

你将这个服务注入到一个很棒的组件中

[Inject]
public AppState AppState { get; set; }

然后你用一个从 web api 获取的新组件实例来擦除这个组件实例

protected override async Task OnInitializedAsync()
{
    AppState = await Http.GetJsonAsync<AppState>(ConfigFiles.GetPath("appsettings.json"));
    await Task.FromResult(0);
}

他们的代码又很奇怪,应该是

protected override async Task OnInitializedAsync()
{
    AppState = await Http.GetJsonAsync<AppState>(ConfigFiles.GetPath("appsettings.json"));
}

但这不会重置您在第二个组件中注入的单例实例。这只是替换您的第一个组件中的实例。

  • 您应该向
  • 注册您的服务
services.AddSingleton<AppState>(provider =>
{
    var http = provider.GetRequiredService<HttpClient>();
    return http.GetJsonAsync<AppState>(ConfigFiles.GetPath("appsettings.json")).ConfigureAwait(false).GetAwaiter().GetResult();
});

这样,您在应用生命周期中只需调用一次 appsettings.json

  • 并删除OnInitializedAsync 代码。

异步

但实际上,实现这一目标的最佳方法是注册 Task 返回您的设置

services.AddSingleton(provider =>
{
    var http = provider.GetRequiredService<HttpClient>();
    return http.GetJsonAsync<AppState>("appsettings.json");
});

你可以将它注入到你的组件中

[Inject]
public Task<AppState> AppStateAsync { get; set; }

public AppState AppState { get; set; }

protected override async Task OnInitializedAsync()
{
    AppState = await AppStateAsync;
}

并与它一起使用

@page "/"
@inherits IndexComponent

<p>@AppState.BaseUrl</p>

【讨论】:

  • 如果我把我的代码放在 startup.cs 中,应用程序不会启动,只是一个白色的空白页面,上面写着 Loading..... 永远,我的更新代码是 services.AddSingleton(provider => { var http = provider.GetRequiredService(); return http.GetJsonAsync(ConfigFiles.GetPath("appsettings.json")).GetAwaiter().GetResult(); });
  • 试试http.GetJsonAsync&lt;AppConfig&gt;(ConfigFiles.GetPath("appsettings.json")).ConfigureAwait(false).GetAwaiter().GetResult();
  • ConfigFiles.GetPath("appsettings.json") 是什么?
  • 在 wwwroot 下有一个以 ConfigFiles 命名的文件夹,在 appsetting.json 下。 ConfigFiles.GetPath("appsettings.json") 只是返回 Path.Combine("ConfigFiles", "appsetting.json");
  • Path.Combine() 用于文件名。客户端只有 URL。它的工作原理是一个小奇迹。
猜你喜欢
  • 2014-04-25
  • 2011-11-24
  • 2012-06-04
  • 1970-01-01
  • 2021-10-14
  • 1970-01-01
  • 2020-05-16
  • 2021-04-14
相关资源
最近更新 更多