Совместное использование данных через службу в ASP.NET Blazor (на стороне клиента)

Я использую общую службу в приложении MVC, регистрирую ее как временную службу и получаю доступ к ее значению во всем приложении без каких-либо проблем.

Я попытался реализовать тот же механизм в моем приложении 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);
    }
}

Пытался распечатать базовый URL в файле index.razor

@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>

Здесь он пуст, он зарегистрирован как сервис для обмена данными между компонентами, разве он не должен иметь значение для всего приложения после того, как он установлен ??


person Saurabh    schedule 27.09.2019    source источник
comment
Измените AppState = await Http.GetJsonAsync ‹AppState› (ConfigFiles.GetPath (appsettings.json)); на var appState = await Http.GetJsonAsync ‹AppState› (ConfigFiles.GetPath (appsettings.json )); AppState.BaseUrl = appState.BaseUrl;   -  person Phat Huynh    schedule 27.09.2019
comment
Хорошо, это сработало, какова концепция. В будущем в файлах json будет много ключей, и мне придется устанавливать их один за другим таким образом.   -  person Saurabh    schedule 27.09.2019
comment
Просто измените AppState, не устанавливайте другое значение. Если есть много полей, просто перенесите его в другой класс.   -  person Phat Huynh    schedule 27.09.2019
comment
Хорошо, но как это работает после AppState.BaseUrl = appState.BaseUrl; , Вы можете прояснить это   -  person Saurabh    schedule 27.09.2019
comment
Вы регистрируете AppState как синглтон, я назвал его экземпляром A, когда вы вводите в свой компонент, он по-прежнему является экземпляром A, и вы устанавливаете AppState в своем компоненте с результатом из API, это будет экземпляр B, без эффекта для экземпляра A.   -  person Phat Huynh    schedule 27.09.2019


Ответы (1)


1-й вы регистрируете одноэлементный экземпляр

services.AddSingleton<AppState, AppState>();

для меня это выглядит немного странно. ИМХО так и должно быть

services.AddSingleton<IAppState, AppState>();

or

services.AddSingleton<AppState>();

Но проблема не в этом.

Вы добавляете эту услугу в компонент, и это здорово.

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

И вы стираете этот экземпляр компонента с новым, полученным из веб-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"));
}

Но это не сбрасывает экземпляр singleton, который вы вводите во второй компонент. Это просто заменит экземпляр в вашем 1-м компоненте.

  • Вы должны зарегистрировать свою службу с
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>
person agua from mars    schedule 27.09.2019
comment
Если я помещаю свой код в startup.cs, приложение не запускается, просто белая пустая страница с надписью «Загрузка ... навсегда», мой код обновления - это services.AddSingleton ‹IAppConfig, AppConfig› (provider = ›{var http = provider.GetRequiredService ‹HttpClient› (); return http.GetJsonAsync ‹AppConfig› (ConfigFiles.GetPath (appsettings.json)). GetAwaiter (). GetResult ();}); - person Saurabh; 27.09.2019
comment
Попробуйте с http.GetJsonAsync<AppConfig>(ConfigFiles.GetPath("appsettings.json")).ConfigureAwait(false).GetAwaiter().GetResult(); - person agua from mars; 27.09.2019
comment
Что такое ConfigFiles.GetPath("appsettings.json")? - person agua from mars; 27.09.2019
comment
В папке wwwroot есть папка с именем ConfigFiles, в папке appsetting.json. ConfigFiles.GetPath (appsettings.json) просто верните Path.Combine (ConfigFiles, appsetting.json); - person Saurabh; 27.09.2019
comment
Path.Combine () предназначен для имен файлов. На стороне клиента у вас есть только URL-адреса. Неудивительно, что это работает. - person Henk Holterman; 27.09.2019
comment
@HenkHolterman, после удаления Path.Combine и предоставления простого URL-адреса как ConfigFiles / appsettings.json результат такой же, похоже, из startuhiship.cs этот путь не найден и, следовательно, пустая белая страница .... - person Saurabh; 28.09.2019
comment
@HenkHolterman, даже если я введу еще один уровень (как услугу, как у нас в angular) для получения информации из json через httpcall, он недоступен. Похоже, URL-адрес папки wwwroot доступен только со страницы бритвы или ее файла Basecomponent - person Saurabh; 28.09.2019
comment
@HenkHolterman Просто чтобы добавить немного информации, ошибка для пустой белой страницы - Uncaught (в обещании) RangeError: превышен максимальный размер стека вызовов - person Saurabh; 28.09.2019