在 aspnet 核心 SPA Angular 应用程序中返回 404 状态代码

Posted

技术标签:

【中文标题】在 aspnet 核心 SPA Angular 应用程序中返回 404 状态代码【英文标题】:Return 404 status code in aspnet core SPA Angular application 【发布时间】:2018-03-28 09:22:44 【问题描述】:

我正在使用 Angular SPA 项目模板为 dotnet core(VS2017 和 dotnet core 2.0 中可用的模板)开发一个项目。

如果用户访问无效的 URL,我有一个 Angular 组件来显示“未找到”消息。

我还启用了服务器端预渲染。从服务器返回预呈现的“未找到”页面时,如何使其返回 404 的 HTTP 状态代码?

我发现的每种方法都使用 Express 作为后端网络服务器,我无法在 aspnet 核心后端上找到任何资源。

感谢您的帮助!


为清楚起见进行编辑:

我不希望针对特定 MVC 控制器操作或应用程序错误返回 404。

我希望从特定的 Angular2/4 组件返回 404,由 Microsoft.AspNetCore.SpaServices 在服务器端呈现。

作为比较,here 是在 NodeJS 上使用 Express Web 服务器和 Angular Universal 用于服务器端渲染的解决方案示例。

【问题讨论】:

我认为这会对你有所帮助***.com/questions/667053/… 更好***.com/questions/37690114/… 感谢您的建议,但这些都不能解决我的问题。他们都在谈论从标准 ASP.Net/ASPNet Core 应用程序返回 404 响应,而不是服务器端渲染的 Angular 组件。为了清楚起见,我编辑了我的问题。 【参考方案1】:

我找到了解决办法。

首先,我们需要创建一个组件可以用来设置状态码的可注入服务:

import  Injectable  from '@angular/core';

@Injectable()
export class HttpStatusCodeService 

  private statusCode: number;

  constructor()
    this.statusCode = 200;
  

  public setStatusCode(statusCode: number) 
    this.statusCode = statusCode;
  

  public getStatusCode(): number 
    return this.statusCode;
  

我们需要将此服务添加到主AppModule 模块中的providers 数组中:

...
providers: [
    ...
    HttpStatusCodeService,
    ...
]
...

然后我们需要在 boot.server.ts 文件中添加两行(加上 import 语句)(注意这是基于 VS2017 模板创建的 stock 文件):

import 'reflect-metadata';
import 'zone.js';
import 'rxjs/add/operator/first';
import  APP_BASE_HREF  from '@angular/common';
import  enableProdMode, ApplicationRef, NgZone, ValueProvider  from '@angular/core';
import  platformDynamicServer, PlatformState, INITIAL_CONFIG  from '@angular/platform-server';
import  createServerRenderer, RenderResult  from 'aspnet-prerendering';
import  AppModule  from './app/app.module.server';

//ADD THIS LINE
import  HttpStatusCodeService  from './path/to/services/http-status-code.service';

enableProdMode();

export default createServerRenderer(params => 
    const providers = [
         provide: INITIAL_CONFIG, useValue:  document: '<app></app>', url: params.url  ,
         provide: APP_BASE_HREF, useValue: params.baseUrl ,
         provide: 'BASE_URL', useValue: params.origin + params.baseUrl ,
    ];

    return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => 
        const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
        const state = moduleRef.injector.get(PlatformState);
        const zone = moduleRef.injector.get(NgZone);

        //ADD THIS LINE: this will get the instance of the HttpStatusCodeService created for this request.
        const statusCodeService = moduleRef.injector.get(HttpStatusCodeService); 

        return new Promise<RenderResult>((resolve, reject) => 
            zone.onError.subscribe((errorInfo: any) => reject(errorInfo));
            appRef.isStable.first(isStable => isStable).subscribe(() => 
                // Because 'onStable' fires before 'onError', we have to delay slightly before
                // completing the request in case there's an error to report
                setImmediate(() => 
                    resolve(
                        html: state.renderToString(),

                        //ADD THIS LINE: this will get the currently set status code and return it along with the prerendered html string
                        statusCode: statusCodeService.getStatusCode() 
                    );
                    moduleRef.destroy();
                );
            );
        );
    );
);

最后我们需要在任何不应该返回 HTTP 200 的组件中设置状态码:

import  Component  from '@angular/core';

import  HttpStatusCodeService  from './path/to/services/http-status-code.service';

@Component(
    selector: 'not-found',
    templateUrl: './not-found.html'
)
export class NotFoundComponent 

  constructor(private httpStatusCodeService: HttpStatusCodeService) 
    httpStatusCodeService.setStatusCode(404);
  

【讨论】:

能否请您指导如何在新的基于 Angular CLI 的 .net github.com/aspnet/javascriptServices/issues/… 模板中处理这个问题。我认为角度部分基本相同,但我无法弄清楚 .net 部分。 没有 .NET 部分,上面的答案都是 Angular。看起来基于 Angular CLI 的模板发生了很大变化,包括 Angular 应用程序的构建和引导方式。浏览模板的Startup.cs 文件 (go.microsoft.com/fwlink/?linkid=864501) 中引用的文档,看起来您需要添加一个类似于 RTM 模板中的boot.server.tsmain.server.ts 文件,但是它足够不同,我不知道如何在其中处理这个问题,我现在也没有时间尝试弄清楚。 Entith,您能看看这个***.com/a/50937983/2755616 并分享您对这种基于 Angular CLI 模板的方法的反馈吗?

以上是关于在 aspnet 核心 SPA Angular 应用程序中返回 404 状态代码的主要内容,如果未能解决你的问题,请参考以下文章

生产 SPA 上的 Angular 应用程序 Http 解析错误

如何为在 IIS 上运行的 aspnet 核心应用程序在 appsettings.json 中配置 IdentityServer 的关键设置

Angular 4 对 asp.net 核心 API 的请求(在标头中使用授权)不起作用

如何保护 Angular 2 SPA 免受 XSS 攻击?

流式 RTSP(AspNet 5 API、FFMPEG、Angular 10、videoJs)[已解决]

在运行 angular spa 之前等待 $http