#asp.net-core #blazor #blazor-webassembly
Вопрос:
Существует объект типа AuthenticationState с именем «контекст», доступный внутри компонентов AuthorizeView и AuthorizedRouteView. Этот объект позволяет получить доступ к ClaimsPrincipal через context.User.
Я вижу в исходном коде, что состояние аутентификации передается этим компонентам как задача компонентом CascadingValue, реализованным в компоненте CascadingAuthenticationState (который, в свою очередь, определен в верхней части иерархии компонентов в App.razor).
Однако, когда я проверяю источник AuthorizeRouteView, я вижу каскадный параметр задачи типа с именем ExistingCascadedAuthenticationState. Тем не менее, для меня остается полной загадкой, как и где Задача раскрывается и раскрывается как «контекст». Кто-нибудь знает ответ?
Ответ №1:
Вам нужно копнуть глубже, и это немного сложно.
AuthorizeView
наследует отAuthorizeViewCore
AuthorizedRouteView
строит его самостоятельноAuthorizeRouteViewCore
, унаследовав отAuthorizeViewCore
.
Код в нижней части AuthorizedRouteView
:
private sealed class AuthorizeRouteViewCore : AuthorizeViewCore
{
[Parameter]
public RouteData RouteData { get; set; } = default!;
protected override IAuthorizeData[]? GetAuthorizeData()
=> AttributeAuthorizeDataCache.GetAuthorizeDataForType(RouteData.PageType);
}
AuthorizedRouteView
захватывает любой каскад в ExistingCascadedAuthenticationState
. Если он существует (не нулевой), то CascadingAuthenticationState
существует внутри App
, так что больше ничего не нужно делать. Если он равен нулю, то он добавляет CascadingAuthenticationState
в качестве корневого компонента компонент в свой фрагмент рендеринга. Это гарантирует, что Task<AuthenticationState>
это каскадно.
AuthorizeViewCore
захватывает каскадное значение:
[CascadingParameter] private Task<AuthenticationState>? AuthenticationState { get; set; }
Он «разворачивается» в OnParametersSetAsync
currentAuthenticationState = await AuthenticationState;
isAuthorized = await IsAuthorizedAsync(currentAuthenticationState.User);
и используется в BuildRenderTree
том «контексте», который вы видите.
var authorized = Authorized ?? ChildContent;
builder.AddContent(0, authorized?.Invoke(currentAuthenticationState!));
Содержание исходит от:
RenderFragment<TValue>
объявляется следующим образом, где TValue
— content
— объявляется как AuthenticationState
:
[Parameter] public RenderFragment<AuthenticationState>? Authorized { get; set; }
Комментарии:
1. Это полный ответ, спасибо! Может быть, вы могли бы просто добавить примечание в конце, что
AuthenticationState
входRenderFragment<AuthenticationState>
отображается какcontent
, потому что, когда у нас естьRenderFragment<TValue>
делегат,<TValue>
он по умолчанию отображается какcontext
?2. @Нейтс. Спасибо, я сделал мод для
RenderFragment<TValue>
.
Ответ №2:
Комментарий энета помог мне найти ответ.
Когда у нас есть RenderFragment<TValue>
делегат, <TValue>
он по умолчанию отображается как @context
.
Например, в AuthorizeRouteView
у нас есть параметр NotAuthorized
:
[Parameter]
public RenderFragment<AuthenticationState> NotAuthorized { get; set; }
В данном случае AuthenticationState
есть TValue
, следовательно AuthenticationState
, выставляется как @context
.
Эта статья об Университете Блейзора стала для меня ключом к пониманию концепции: передача заполнителей в фрагменты визуализации.
Комментарии:
1. Добавьте также «Шаблонных делегатов Razor» в сделку: docs.microsoft.com/en-us/aspnet/core/mvc/views/…
2. [Вежливо] Рад, что вы разгадали это, но ваш вопрос был «Все же для меня полная загадка, как и где раскрывается задача», на которую ваш ответ на самом деле не отвечает.
Ответ №3:
Параметр каскадирования Task<AuthenticationState> context
указывает , что context
при ожидании будет возвращен объект типа AuthenticationState. Итак, то, что вы получаете, — это Задача. Задача, когда ее ожидают, возвращает значение, возвращенное Задачей. Фактический синтаксис для доступа к Пользователю таков
var state = await context;
var user = state.User;
Кроме того, вы можете дать любое имя параметру каскадирования. Так
[CascadingParameter]
public Task<AuthenticationState> AuthState {get;set;}
var state = await AuthState;
var user = state.User;
в равной степени справедливо.
Комментарии:
1. Я не думаю, что вы поняли вопрос… Вот несколько подсказок, которые помогут вам создать новый ответ: делегат Razor с шаблоном ( это часть Razor), делегат фрагментации ( Blazor). ОП на самом деле хочет знать, что такое «контекст», как и где он создается.
2. Параметр каскадирования в AutyhorizeRouteView кодируется как «частная задача<Состояние проверки подлинности> Существующее состояние проверки подлинности { get; set; }». Я также знаю, что каскадные параметры связаны по их типу, и поэтому вы можете их назвать. Но чего мне не хватает, так это той части, где ожидается состояние ExistingCascadedAuthenticationState и присваивается объекту с именем «контекст».
3. Спасибо @enet. Но здесь я немного сбит с толку. Потому что вы упомянули AuthenticationState в одной части вопроса и перешли к ExistingCascadedAuthenticationState . Источник указывает, что только в том случае, если у вас есть существующее состояние ExistingCascadedAuthenticationState (т. Е. Не null), вы создаете дочернее состояние и ничего не делаете. Это связано с тем, что это каскадный параметр, и вы позволяете дочерним компонентам решать, что с ним делать. Если у вас нет существующего состояния проверки подлинности, вы создаете фрагмент визуализации, добавляя новый каскадный параметр типа AuthenticationState.
4. github.com/dotnet/aspnetcore/blob/… «защищенное переопределение недействительного рендеринга(RenderTreeBuilder builder)» — это место, где применяется эта проверка (Ln 73). Если это отрицательно, создается новый компонент AuthenticationState (Ln 82 в соответствии с документацией на Ln 16)