如何在 Razor Page OnInitialized 事件中使用 404 路由

Lar*_*tig 13 c# .net-core razor-pages blazor-server-side

在服务器端 Blazor 应用程序 (Core 3.1) 中,有一个接受@page属性中的标识符的 Razor。如果 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));
    }

}
Run Code Online (Sandbox Code Playgroud)

May*_*ote 5

如果您想在显示错误 404 时“保持”在同一条路线上:

创建一个类 NotFoundListener.cs

public class NotFoundListener
    {
        public  Action OnNotFound { get;set; }

        public void NotifyNotFound()
        {
            if(NotifyNotFound != null)
            {
                OnNotFound.Invoke();
            }
        }

    }
Run Code Online (Sandbox Code Playgroud)

将其作为范围服务注入

builder.Services.AddScoped<NotFoundListener>();
Run Code Online (Sandbox Code Playgroud)

在你的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://learn.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();
    }

}
Run Code Online (Sandbox Code Playgroud)

而在你想引发404的页面中:

protected override void OnInitialized()
{
    if (project == null)
    {
        nfl.NotifyNotFound();
    }
}
Run Code Online (Sandbox Code Playgroud)

这会:

  1. 让您在浏览器中保持相同的路线
  2. 无法导航到任何地方
  3. 确保每个页面上都没有 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>
Run Code Online (Sandbox Code Playgroud)

您可以创建自己的NotFoundComponent.razor组件

<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
    <p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
Run Code Online (Sandbox Code Playgroud)

您的更新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>
Run Code Online (Sandbox Code Playgroud)

然后您可以创建一个仅引用同一组件的页面

未找到页面.razor

@page "/NotFound"

<NotFoundComponent />
Run Code Online (Sandbox Code Playgroud)

然后使用页面重定向,如下所示

从你的 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));
    }
}
Run Code Online (Sandbox Code Playgroud)


Raf*_*Ali 2

这是代码片段

@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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @RafaqatAli,使用这种方法,你不会最终得到“/404”吗?“未找到响应”不应导致重定向到另一个页面,而应让用户停留在无法找到内容的 URL。 (4认同)
  • 使用此解决方案,应用程序可能会认为我正在尝试导航到名为 404 的_project_,然后该项目会重定向到 404 并生成 Too Many Redirects 错误。我假设“404”字符串没有特殊含义,只会根据我设置的任何路由进行路由——并且我需要使用保证不会被我的应用程序处理的东西? (2认同)