如何在 Razor Page OnInitialized 事件中使用 404 路由
Posted
技术标签:
【中文标题】如何在 Razor Page OnInitialized 事件中使用 404 路由【英文标题】:How to use 404 routing in Razor Page OnInitialized event 【发布时间】:2020-04-15 19:33:17 【问题描述】:在服务器端 Blazor 应用程序 (Core 3.1) 中,有一个 Razor 接受 @page
属性中的标识符。如果 URL 中提供的标识符对应于现有实体,则页面将正常呈现。但是,如果标识符不是已知实体(由其在存储库中的存在确定),我希望系统执行与 404 Not Found 对应的任何操作。但是,在路由已经匹配并且我的页面的 OnInitialized()
正在执行之前,我不知道这一点。
在这种情况下如何“重定向”到默认的 404 处理。
页面如下所示:
@page "/projectname"
<!-- html Here -->
@code
[Parameter]
public string ProjectName get; set;
private UpdateProjectViewModel Project;
protected override void OnInitialized()
var project = Repository.Get(ProjectName);
if (project == null)
WANT TO USE 404 ROUTING HERE.
Project = new UpdateProjectViewModel(project));
【问题讨论】:
通过@inject NavigationManager navMgr
和navMgr.NavigateTo("/404",false);
注入一个NavigationManager ?
仅供参考,如果你沿着这条路线走,把它放在 AfterRender 方法中,否则 navimanager 会抛出异常
恐怕没有什么比 page.razor 文件中的简单 if/else 更好的了。我在页面顶部做了这样的事情:@if(_notFound) <NotFoundComponent /> return;
。 return 语句允许我跳过 else
块并防止嵌套在组件的其余部分中。
【参考方案1】:
如果您想在显示错误 404 的同时“保持”在同一条路线上:
创建一个类NotFoundListener.cs
public class NotFoundListener
public Action OnNotFound get;set;
public void NotifyNotFound()
if(NotifyNotFound != null)
OnNotFound.Invoke();
将其作为作用域服务注入
builder.Services.AddScoped<NotFoundListener>();
在你的MainLayout.razor
@inherits LayoutComponentBase
@inject NotFoundListener nfl;
<PageTitle>ImportTesting</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@if (notFound)
<h1>Could not find the content you are looking for</h1>
else
@Body
</article>
</main>
</div>
@code
private bool notFound;
protected override void OnInitialized() => nfl.OnNotFound += SetNotFound;
void SetNotFound()
notFound = true;
StateHasChanged();
并且在你要引发 404 的页面中:
protected override void OnInitialized()
if (project == null)
nfl.NotifyNotFound();
这将:
-
让您在浏览器中保持同一路线
不导航到任何地方
确保每一页都没有 if else
(我用Action来处理事件,不是最好的使用方式,但是让代码更容易阅读)
现在,
您可以为不同的页面设置不同的事件侦听器。 您可以根据具体需要创建不同的布局。 如果您只想在某些页面而不是所有页面上应用此功能,请添加 'route' 事件的参数并在 MainLayout 上检查它。如果您想重复使用标准错误页面:
您的错误页面在您的 App.razor 中定义
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
您可以创建自己的NotFoundComponent.razor
组件
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
您更新后的App.razor
如下所示:
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<NotFoundComponent/>
</NotFound>
</Router>
然后你可以创建一个简单地引用同一个组件的页面
NotFoundPage.razor
@page "/NotFound"
<NotFoundComponent />
然后使用您的页面重定向如下
来自您的 OnInitialized()
@page "/projectname"
<!-- HTML Here -->
@code
[Parameter]
public string ProjectName get; set;
private UpdateProjectViewModel Project;
protected override void OnInitialized()
var project = Repository.Get(ProjectName);
if (project == null)
NavigationManager.NavigateTo("/NotFound");
Project = new UpdateProjectViewModel(project));
【讨论】:
感谢您的尝试,但我想显示路由不匹配时已经显示的标准 404 错误。我不想重新发明在我想要这样做的每个页面中显示的 404 页面,也不想将 html 部分与分支逻辑混淆。 你的意思是浏览器显示的页面?如果是,您想在地址栏中看到什么? 更新了我的答案,请检查是否是您需要的。 正确,但这仍然会重定向用户。请参阅罗斯 P 在另一个答案中的评论,“使用这种方法,您不会以“/404”结束吗?“未找到响应”不应导致重定向到另一个页面,而是将用户保留在内容可能的 url找不到。” 更新了答案。我已经测试过了。【参考方案2】:这里是代码sn-p
@page "/navigate"
@inject NavigationManager NavigationManager
<h1>Navigate in Code Example</h1>
<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
Navigate to the Counter component
</button>
@code
private void NavigateToCounterComponent()
NavigationManager.NavigateTo("404");
【讨论】:
使用此解决方案,可能应用程序认为我正在尝试导航到名为 404 的 项目,然后重定向到 404 并生成太多重定向错误。我假设“404”字符串没有特殊含义,只会根据我设置的任何路由进行路由——我需要使用一些保证不会被我的应用程序处理的东西? 您需要放置一个组件来代替 404。这里是您可以获得帮助的链接:docs.microsoft.com/en-us/aspnet/core/blazor/… @RafaqatAli,使用这种方法,您不会以“/404”结尾吗? “未找到响应”不应导致重定向到另一个页面,而是将用户留在无法找到内容的 url。 你找到这个@RossP 的解决方案了吗?我同意你的看法,这个答案不是解决方案,也不是“正确”的 404。以上是关于如何在 Razor Page OnInitialized 事件中使用 404 路由的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ASP.NET Core 同时制作 Razor Page 和 C# 代码框架?
JSON.stringify 作为 Null 传入 Razor-Page
ASP.NET Core Razor Pages 强制 Anchor Tag Helper (asp-page) 使用小写路由