【问题标题】:How does cascaded parameter Task<AthenticationState> get unwrapped and exposed as "context" in AuthorizeView and AuthorizedRouteView in Blazor WASM?级联参数 Task<AthenticationState> 如何在 Blazor WASM 中的 AuthorizeView 和 AuthorizedRouteView 中展开并暴露为“上下文”?
【发布时间】:2021-12-04 23:13:54
【问题描述】:

AuthorizeView 和 AuthorizedRouteView 组件中有一个名为“context”的 AuthenticationState 类型的对象。该对象允许通过 context.User 访问 ClaimsPrincipal。

我可以在源代码中看到 AuthenticationState 通过 CascadingAuthenticationState 组件中实现的 CascadingValue 组件作为 Task 传递给这些组件(该组件又在 App.razor 中组件层次结构的顶部定义)。

但是,当我检查 AuthorizeRouteView 的源时,我可以看到名为 ExistingCascadedAuthenticationState 的 Task 类型的级联参数。然而,对我来说,任务是如何以及在哪里被解包并暴露为“上下文”是一个完全的谜。有人知道答案吗?

【问题讨论】:

    标签: asp.net-core blazor blazor-webassembly


    【解决方案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&lt;AuthenticationState&gt; 是级联的。

    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; }
    

    【讨论】:

    • 这是完整的答案,谢谢!也许您可以在末尾添加注释,即RenderFragment&lt;AuthenticationState&gt; 中的AuthenticationState 公开为content,因为当我们有一个RenderFragment&lt;TValue&gt; 委托时,&lt;TValue&gt; 默认公开为context?跨度>
    • @Neits。谢谢,我已经为RenderFragment&lt;TValue&gt; 制作了模组。
    【解决方案2】:

    enet 的评论帮我找到了答案。

    当我们有一个RenderFragment&lt;TValue&gt; 委托时,&lt;TValue&gt; 默认公开为@context

    例如,在AuthorizeRouteView 中我们有一个参数NotAuthorized

     [Parameter]
     public RenderFragment<AuthenticationState> NotAuthorized { get; set; }
    

    在这种情况下AuthenticationStateTValue,因此AuthenticationState 暴露为@context

    这篇关于 Blazor 大学的文章是我了解这个概念的关键:Passing placeholders to RenderFragments

    【讨论】:

    • 将“Templated Razor delegates”添加到交易中:docs.microsoft.com/en-us/aspnet/core/mvc/views/…
    • [礼貌] 很高兴你解开了它,但你的问题是“然而,对我来说,任务是如何以及在哪里解开的完全是个谜”,而你的答案并没有真正回答。跨度>
    【解决方案3】:

    级联参数为Task&lt;AuthenticationState&gt; 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;
    

    同样有效。

    【讨论】:

    • 我认为您没有理解这个问题...这里有一些线索可以帮助您创建新的答案:模板化 Razor 委托(这是 Razor 的一部分)、RenderFragment 委托(Blazor) . OP 实际上想知道什么是“上下文”,它是如何以及在哪里产生的。
    • AuthyhorizeRouteView 中的级联参数编码为“private Task ExistingCascadedAuthenticationState { get; set; }”。我也知道级联参数与它们的类型相关,因此您可以命名它们。但是我缺少的是等待 ExistingCascadedAuthenticationState 并将其分配给名为“context”的对象的部分。
    • 感谢@enet。但我在这里有点困惑。因为您在问题的一部分中提到了 AuthenticationState 并移至 ExistingCascadedAuthenticationState 。源代码指定只有当你有一个现有的 ExistingCascadedAuthenticationState (即不为空)时,你才会构建孩子并且什么都不做。那是因为它是一个级联参数,您让子组件决定如何处理它。如果您没有 ExistingCascadedAuthenticationState,那么您构建一个渲染片段,添加一个新的 AuthenticationState 类型的 CascadingParameter。
    • github.com/dotnet/aspnetcore/blob/… 'protected override void Render(RenderTreeBuilder builder)' 是应用此检查的地方 (Ln 73)。如果是否定的,则创建新的 AuthenticationState 组件(根据 Ln 16 上的文档,Ln 82)
    猜你喜欢
    • 2021-07-28
    • 2021-03-06
    • 2021-12-07
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 2017-06-21
    相关资源
    最近更新 更多