我想在下面的错误中指定布局。
- 未找到路由
- 未经授权
- 禁止
文件详细信息
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>
我尝试过的
根据文件详细信息中的描述,ErrorLayout用于Error404,但MainLayout应用于Error401和Error403。
我尝试了以下描述,但不起作用。
添加@布局
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>
问题
在授权和身份验证错误的情况下,我如何编写路由器来指定布局?
@layout是否只对带有@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);
}
您可以将其扩展为包括返回地址等
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导航的情况下做我想做的事情。
完整来源
- GitHub
一种更简单的方法是在MainLayout.razor
文件中设置适当的布局。像这个
@inherits LayoutComponentBase
<!-- Page wrapper -->
<AuthorizeView>
<Authorized>
<div class="flex flex-row h-screen bg-slate-50 overflow-hidden">
<!-- Side Bar-->
<SideBar/>
<!-- Content area -->
<div class="">
<!-- site header -->
<HeaderLayout/>
<main>
<div class="px-4 sm:px-6 lg:px-8 py-8 bg-slate-50">
@Body
</div>
</main>
</div>
</div>
</Authorized>
<NotAuthorized>
@Body
</NotAuthorized>
<Authorizing>
<p>Hold up, lemma check you out.</p>
</Authorizing>
</AuthorizeView>