Как интерактивные компоненты получают параметр в проекте Blazor Static SSR?
Я создал простой проект на GitHub, чтобы продемонстрировать проблему.
Это проект Blazor Static SSR с интерактивными компонентами. В program.cs он использует:
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
Требования: Страницы неинтерактивны (EditForms с отправкой). В проекте не может быть глобально доступной интерактивности (например, Blazor Server).
На многие страницы мы хотим включить интерактивный компонент.
Если неинтерактивная страница содержит интерактивный компонент, Blazor не позволит вам использовать стандартный метод включения такого параметра, как: ChildInteractive userid="aaa" ChildInteractive.
Кажется, что решение устанавливает параметр в program.cs. Это делается с помощью: builder.Services.AddCascadingValue("UserID", sp => (string)"Начальное значение, заданное в Program.cs");
Этот параметр каскадирования доступен всем компонентам.
(Кстати, в проекте Static SSR параметры каскадирования, установленные в Routes.razor, доступны только для неинтерактивных компонентов.)
Мой вопрос: параметр каскадирования устанавливается с помощью builder.Services.AddCascadingValue. Но как изменить значение? В моем случае параметром является идентификатор пользователя для входа. Однако UserID неизвестен до тех пор, пока пользователь не войдет в систему. Поэтому, как только пользователь войдет в систему, необходимо обновить параметр каскадирования UserID.
Пример проекта:
https://github.com/ssperoniGIT/Blazor-SSR-Params
Кажется, единственное решение — установить параметр до запуска проектов, установив его в program.cs. Но его необходимо обновить.
Вы можете использовать функцию «Локальное хранилище браузера», чтобы сохранить личные данные для каждого пользователя. И удалите хранилище при выходе из системы. Но поскольку код SSR C# запускается только на сервере и не имеет доступа к локальному хранилищу браузера, вам необходимо использовать JavaScript. Использовать JavaScript для доступа к локальному хранилищу также очень просто. Вы можете попробовать следующий образец:
1.установите пакет Blazored.LocalStorage
.
Программа.cs
builder.Services.AddBlazoredLocalStorage();
2. Измените ChildInteractive
, как показано ниже: (Я использовал номер счетчика в качестве идентификатора пользователя. Используйте «нажмите меня», чтобы обновить этот идентификатор в хранилище, и используйте «выход», чтобы сбросить идентификатор и очистить хранилище)
@rendermode @(new InteractiveServerRenderMode(prerender: false))
@inject Blazored.LocalStorage.ILocalStorageService localStorage
@inject NavigationManager manager
<p role = "status">Child Current Id: @currentCount</p>
<button class = "btn btn-primary" @onclick = "IncrementCount">Click me</button>
<button class = "btn btn-primary" @onclick = "Clear">LogOut Clear</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
localStorage.SetItemAsStringAsync("UserId",currentCount.ToString());
manager.NavigateTo("/");
}
protected override async Task OnInitializedAsync()
{
var a = await localStorage.GetItemAsStringAsync("UserId");
currentCount = (a != null) ? Int32.Parse(a) : 0;
}
private async Task Clear()
{
currentCount = 0;
await localStorage.RemoveItemAsync("UserId");
manager.NavigateTo("/");
}
}
3. Измените Home.razor, как показано ниже: (Здесь мы используем BlaozrPageScript
, он позволяет выполнять код js при навигации без принудительной перезагрузки https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript- совместимость/статический-сервер-рендеринг?view=aspnetcore-8.0)
@page "/"
@using BlazorPageScript
<PageScript Src = "./Components/Pages/Home.razor.js" />
<p >Parent UserId = <label id = "UserId">0</label></p>
<ChildInteractive></ChildInteractive>
4. Создайте Home.razor.js, как показано ниже:
export function onUpdate() {
var id = localStorage.getItem("UserId");
document.getElementById("UserId").innerHTML = id?id:0;
}
Затем вы обнаружите, что родительский элемент SSR и дочерний элемент InterActive используют одно и то же значение из localstorage и могут обновляться одновременно.
Кстати, официальный шаблон получает идентификацию с помощью PersistingRevalidatingAuthenticationStateProvider
, который использует UserManager, реализующий cookie
аутентификацию. Таким образом, хранилище браузера должно быть правильным направлением.
Спасибо, Цян, ваше решение работает и отвечает на вопрос. Подводя итог, установите два небольших пакета NuGet: Blazored.LocalStorage BlazorPageScript и напишите две строки JavaScript.
Когда пользователь входит в систему, страница обновляется, идентификация присутствует. От этого зависит PersistingRevalidatingAuthenticationStateProvider. Все режимы рендеринга являются первым рендерингом SSR, как вы, вероятно, знаете, если только вы не используете конструктор, чтобы установить для предварительного рендеринга значение false. На странице входа вы увидите шаблон, который они используют: RedirectManager.RedirectTo(ReturnUrl);