如何使用实际的 404 状态代码响应替换 Blazor 默认的“软 404”

Kra*_*orm 9 http-status-code-404 blazor

Blazor 处理 404 的默认方法是在 App.razor 中创建软 404,但我希望遵循搜索引擎最佳实践,在 Azure 上显示 404 页面时实际返回 404 状态代码。

我尝试删除 App.razor 中的元素,看看是否可以强制出现 404,但是,它无法编译。

有什么建议么?

Erg*_*lik 7

我用这个代码。效果很好。

我创建了 Error404Layout。我将这种布局用于 NotFound 部分。

    <Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(Error404Layout)">
            <h2>Oops! That page can't be found.</h2>
        </LayoutView>
    </NotFound>
</Router>
Run Code Online (Sandbox Code Playgroud)

Error404布局内容如下

    @inherits LayoutComponentBase

    @using Microsoft.AspNetCore.Http
    @inject IHttpContextAccessor httpContextAccessor

    @Body

    @code {
        protected override void OnInitialized()
        {
            httpContextAccessor.HttpContext.Response.StatusCode = 404;
       }
    }
Run Code Online (Sandbox Code Playgroud)

您必须在startup.cs / services方法中添加此代码

    public void ConfigureServices(IServiceCollection services)
    {
        ....
        services.AddHttpContextAccessor();
    }
Run Code Online (Sandbox Code Playgroud)

我可以看到 404 状态代码

在此输入图像描述


Mon*_*ode 2

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-3.1确实指出:

此外,出于安全原因,您不得在 Blazor 应用中使用 IHttpContextAccessor。Blazor 应用程序在 ASP.NET Core 管道的上下文之外运行,并且不保证 HttpContext 在 IHttpContextAccessor 中可用,也不保证保存启动 Blazor 应用程序的上下文。

因此,您需要在 IHttpContextAccessor 周围创建一个包装器,以在 Blazor 进行服务器端预渲染时限制这种情况。


在 Blazor WebAssembly 应用程序(ASP.Net Core 托管)模板中使用服务器端预渲染时,我能够返回 404 http 状态代码

当我将浏览器指向 http://localhost/fetchdata 时,它返回了一个页面。我希望它返回 404 状态代码作为示例。使用依赖注入和存根类可以实现这一点。

BlazorApp1.Client中,我添加了一个 IResponse.cs 文件:

namespace BlazorApp1.Client {
    public interface IResponse {
        void SetNotFound();
    }
}
Run Code Online (Sandbox Code Playgroud)

在 BlazorApp1.Client 中,我添加了一个 ResponseStub.cs 文件:

namespace BlazorApp1.Client {
    public class ResponseStub : IResponse {
        public void SetNotFound() {
            // Do nothing if we are browser side
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在 BlazorApp1.Client 的 FetchData.razor 中我添加了:

@inject BlazorApp1.Client.IResponse Response
Run Code Online (Sandbox Code Playgroud)

并在代码部分:

protected override void OnInitialized() {
    Response.SetNotFound();
}
Run Code Online (Sandbox Code Playgroud)

在 BlazorApp1.Client 的 Program.cs 中我添加了:

builder.Services.AddScoped<IResponse, ResponseStub>();
Run Code Online (Sandbox Code Playgroud)

然后在BlazorApp1.Server的Startup.cs 中,我在 ConfigureServices 下添加:

services.AddHttpContextAccessor();
services.AddScoped<IResponse, Response>();
Run Code Online (Sandbox Code Playgroud)

在配置下我替换了:

endpoints.MapFallbackToFile("index.html");
Run Code Online (Sandbox Code Playgroud)

和:

endpoints.MapFallbackToPage("/_Host");
Run Code Online (Sandbox Code Playgroud)

然后在 Response.cs 中创建 IResponse 的服务器实现:

using BlazorApp1.Client;
using Microsoft.AspNetCore.Http;
using System.Net;

namespace BlazorApp1.Server {
    public class Response : IResponse {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public Response(IHttpContextAccessor accessor) {
            _httpContextAccessor = accessor;
        }

        public void SetNotFound() {
            _httpContextAccessor.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,我在 BlazorApp1.Server/Pages 中创建一个 _Host.cshtml 文件:

@page "/fallback"
@namespace BlazorPrerendering.Server.Pages
@using BlazorApp1.Client
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = "_Layout";
}
<app>
    <component type="typeof(App)" render-mode="ServerPrerendered" />
</app>
<div id="blazor-error-ui">
    An unhandled error has occurred.
    <a href="" class="reload">Reload</a>
    <a class="dismiss"></a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
Run Code Online (Sandbox Code Playgroud)