我想为 Blazor 中的身份验证错误指定非默认布局
I want to specify a non-default layout for authentication errors in Blazor
我想在下面的错误中指定布局。
- 找不到路线。
- 未授权。
- 禁止。
文件详细信息
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<!-- TODO RZ9999 when Context removed -->
<AuthorizeView Context="authenticated">
<Authorized>
<!-- TODO ErrorLayout -->
<Error403/>
</Authorized>
<NotAuthorized>
<!-- TODO ErrorLayout -->
<Error401/>
</NotAuthorized>
</AuthorizeView>
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error404/>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Error401.razor、Error403.razor、Error404.razor
<PageTitle>Error401</PageTitle>
<h3>Error401</h3>
<PageTitle>Error403</PageTitle>
<h3>Error403</h3>
<PageTitle>Error404</PageTitle>
<h3>Error404</h3>
我试过的
根据File details中的描述,Error404用的是ErrorLayout,Error401和Error403用的是MainLayout
我尝试了以下描述,但没有用。
添加@layout
Error401.razor 如下,但应用了 MainLayoute。
@layout 只对@page 有效吗?
@layout ErrorLayout
<PageTitle>Error401</PageTitle>
<h3>Error401</h3>
添加布局视图
如果 Error401 和 Error403 是 LayoutView 的子级,它们将嵌套在 MainLayout 和 ErrorLayout 布局中。
<AuthorizeView Context="authenticated">
<Authorized>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error403/>
</LayoutView>
</Authorized>
<NotAuthorized>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error401/>
</LayoutView>
</NotAuthorized>
</AuthorizeView>
问题
如果授权和认证错误,如何编写一个 Router 来指定布局?
Is @layout only valid for those with @page?
是的……您也可以将其添加到布局中以指定嵌套。
仅供参考:401 和 403 都被 <NotAuthorized>
捕获。
使用如下组件:
public class RedirectToPage : ComponentBase
{
[Inject]
private NavigationManager Navigation { get; set; }
[Parameter]
public string Href { get; set; }
protected override void OnInitialized()
=> Navigation.NavigateTo(Href);
}
您可以将其扩展为包含 return 地址等。
在你的App.razor
里面
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated == true)
{
<RedirectToPage Href="/error403" />
}
else
{
<RedirectToPage Href="/error401" />
}
</NotAuthorized>
使用您选择的 @layout ...
创建适当的错误页面。
我通过创建自定义版本的 AuthorizeRouteView 解决了这个问题。
基于 Blazor 源 AuthorizeRouteView 创建具有以下更改的 CustomAuthorizeRouteView。
public sealed class CustomAuthorizeRouteView : RouteView
{
...
[Parameter]
public Type NotAuthorizedLayout { get; set; }
...
private void RenderContentInNotAuthorizedLayout(RenderTreeBuilder builder, RenderFragment content)
{
builder.OpenComponent<LayoutView>(0);
builder.AddAttribute(1, nameof(LayoutView.Layout), NotAuthorizedLayout);
builder.AddAttribute(2, nameof(LayoutView.ChildContent), content);
builder.CloseComponent();
}
private void RenderNotAuthorizedInDefaultLayout(RenderTreeBuilder builder, AuthenticationState authenticationState)
{
var content = NotAuthorized ?? _defaultNotAuthorizedContent;
RenderContentInNotAuthorizedLayout(builder, content(authenticationState));
}
...
}
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<CustomAuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" NotAuthorizedLayout="@typeof(ErrorLayout)">
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated != true)
{
<Error401/>
}
else
{
<Error403/>
}
</NotAuthorized>
</CustomAuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error404/>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
有了这个内容,我可以在没有导航的情况下用原来的 URL 做我想做的事。
完整来源
我想在下面的错误中指定布局。
- 找不到路线。
- 未授权。
- 禁止。
文件详细信息
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<!-- TODO RZ9999 when Context removed -->
<AuthorizeView Context="authenticated">
<Authorized>
<!-- TODO ErrorLayout -->
<Error403/>
</Authorized>
<NotAuthorized>
<!-- TODO ErrorLayout -->
<Error401/>
</NotAuthorized>
</AuthorizeView>
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error404/>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Error401.razor、Error403.razor、Error404.razor
<PageTitle>Error401</PageTitle>
<h3>Error401</h3>
<PageTitle>Error403</PageTitle>
<h3>Error403</h3>
<PageTitle>Error404</PageTitle>
<h3>Error404</h3>
我试过的
根据File details中的描述,Error404用的是ErrorLayout,Error401和Error403用的是MainLayout
我尝试了以下描述,但没有用。
添加@layout
Error401.razor 如下,但应用了 MainLayoute。 @layout 只对@page 有效吗?
@layout ErrorLayout
<PageTitle>Error401</PageTitle>
<h3>Error401</h3>
添加布局视图
如果 Error401 和 Error403 是 LayoutView 的子级,它们将嵌套在 MainLayout 和 ErrorLayout 布局中。
<AuthorizeView Context="authenticated">
<Authorized>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error403/>
</LayoutView>
</Authorized>
<NotAuthorized>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error401/>
</LayoutView>
</NotAuthorized>
</AuthorizeView>
问题
如果授权和认证错误,如何编写一个 Router 来指定布局?
Is @layout only valid for those with @page?
是的……您也可以将其添加到布局中以指定嵌套。
仅供参考:401 和 403 都被 <NotAuthorized>
捕获。
使用如下组件:
public class RedirectToPage : ComponentBase
{
[Inject]
private NavigationManager Navigation { get; set; }
[Parameter]
public string Href { get; set; }
protected override void OnInitialized()
=> Navigation.NavigateTo(Href);
}
您可以将其扩展为包含 return 地址等。
在你的App.razor
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated == true)
{
<RedirectToPage Href="/error403" />
}
else
{
<RedirectToPage Href="/error401" />
}
</NotAuthorized>
使用您选择的 @layout ...
创建适当的错误页面。
我通过创建自定义版本的 AuthorizeRouteView 解决了这个问题。
基于 Blazor 源 AuthorizeRouteView 创建具有以下更改的 CustomAuthorizeRouteView。
public sealed class CustomAuthorizeRouteView : RouteView
{
...
[Parameter]
public Type NotAuthorizedLayout { get; set; }
...
private void RenderContentInNotAuthorizedLayout(RenderTreeBuilder builder, RenderFragment content)
{
builder.OpenComponent<LayoutView>(0);
builder.AddAttribute(1, nameof(LayoutView.Layout), NotAuthorizedLayout);
builder.AddAttribute(2, nameof(LayoutView.ChildContent), content);
builder.CloseComponent();
}
private void RenderNotAuthorizedInDefaultLayout(RenderTreeBuilder builder, AuthenticationState authenticationState)
{
var content = NotAuthorized ?? _defaultNotAuthorizedContent;
RenderContentInNotAuthorizedLayout(builder, content(authenticationState));
}
...
}
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<CustomAuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" NotAuthorizedLayout="@typeof(ErrorLayout)">
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated != true)
{
<Error401/>
}
else
{
<Error403/>
}
</NotAuthorized>
</CustomAuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<Error404/>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
有了这个内容,我可以在没有导航的情况下用原来的 URL 做我想做的事。