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

Posted

技术标签:

【中文标题】如何用实际的 404 状态代码响应替换 Blazor 默认“软 404”【英文标题】:How to replace Blazor default "soft 404" with an actual 404 status code response 【发布时间】:2020-05-31 01:21:37 【问题描述】:

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

我试图删除 App.razor 中的元素以查看是否可以强制执行 404,但是没有编译。

有什么建议吗?

【问题讨论】:

【参考方案1】:

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

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

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

namespace BlazorApp1.Client 
    public interface IResponse 
        void SetNotFound();
    

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

namespace BlazorApp1.Client 
    public class ResponseStub : IResponse 
        public void SetNotFound() 
            // Do nothing if we are browser side
        
    

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

@inject BlazorApp1.Client.IResponse Response

在代码部分:

protected override void OnInitialized() 
    Response.SetNotFound();

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

builder.Services.AddScoped<IResponse, ResponseStub>();

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

services.AddHttpContextAccessor();
services.AddScoped<IResponse, Response>();

在配置下我替换了:

endpoints.MapFallbackToFile("index.html");

与:

endpoints.MapFallbackToPage("/_Host");

然后在Response.cs中创建IResponse的Server实现:

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;
        
    

最后我在 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>

警告 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-3.1 声明:

此外,再次出于安全原因,您不得使用 Blazor 应用程序中的 IHttpContextAccessor。 Blazor 应用程序在外部运行 ASP.NET Core 管道的上下文和 HttpContext 不是 保证在 IHttpContextAccessor 中可用,也不是 保证持有启动 Blazor 应用程序的上下文。

这就是我限制此服务器端预渲染 Blazor 和 OnInitialized 的原因(也应该与 OnInitializedAsync 一起使用)。

【讨论】:

【参考方案2】:

我使用此代码。它运作良好。 我创建了 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>

Error404Layout 内容如下

@inherits LayoutComponentBase

@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor httpContextAccessor

@Body

@code 
    protected override void OnInitialized()
    
        httpContextAccessor.HttpContext.Response.StatusCode = 404;
   

你必须在startup.cs/services方法中添加这段代码

public void ConfigureServices(IServiceCollection services)

    ....
    services.AddHttpContextAccessor();

我可以看到 404 状态码

【讨论】:

感谢您的回复。你确定这总是返回一个httpcontext。根据这个可能会有一些问题:docs.microsoft.com/en-us/aspnet/core/fundamentals/… 我正在寻找更好的方法。

以上是关于如何用实际的 404 状态代码响应替换 Blazor 默认“软 404”的主要内容,如果未能解决你的问题,请参考以下文章

如何用ajax响应替换整个html网页?

ReactJs 上下文 - 如何用传入的状态替换当前组件状态

如何用 apollo 客户端状态管理替换 vuex?

如何用一个条目替换另一个 MS Access 报告?

如何用 Charles 模拟 HTTP 错误响应?

如何用同一数据框中其他列的实际列值替换一列中的字符串值?