Как каскадная задача с параметрами раскрывается и отображается как «контекст» в AuthorizeView и AuthorizedRouteView в Blazor WASM?

#asp.net-core #blazor #blazor-webassembly

Вопрос:

Существует объект типа AuthenticationState с именем «контекст», доступный внутри компонентов AuthorizeView и AuthorizedRouteView. Этот объект позволяет получить доступ к ClaimsPrincipal через context.User.

Я вижу в исходном коде, что состояние аутентификации передается этим компонентам как задача компонентом CascadingValue, реализованным в компоненте CascadingAuthenticationState (который, в свою очередь, определен в верхней части иерархии компонентов в App.razor).

Однако, когда я проверяю источник AuthorizeRouteView, я вижу каскадный параметр задачи типа с именем ExistingCascadedAuthenticationState. Тем не менее, для меня остается полной загадкой, как и где Задача раскрывается и раскрывается как «контекст». Кто-нибудь знает ответ?

Ответ №1:

Вам нужно копнуть глубже, и это немного сложно.

  1. AuthorizeView наследует от AuthorizeViewCore
  2. 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)