Return aspnet core SPA Angular 应用程序中的 404 状态代码
Return 404 status code in aspnet core SPA Angular application
我正在使用 Angular dotnet core 的 SPA 项目模板(在 VS2017 和 dotnet core 2.0 中可用)开发一个项目。
我有一个 Angular 组件可以在用户转到无效 URL 时显示 "Not Found" 消息。
我还启用了服务器端预渲染。当 return 从服务器 "Not Found" 预呈现页面时,我如何使它 return 成为 404 的 HTTP 状态代码?
我发现执行此操作的每个方法都使用 Express 作为后端网络服务器,我无法找到在 aspnet 核心后端执行此操作的任何资源。
感谢您的帮助!
为清楚起见编辑:
我不希望 return 特定 MVC 控制器操作或应用程序错误的 404。
我正在寻找 return 来自特定 Angular2/4 组件的 404,由 Microsoft.AspNetCore.SpaServices 在服务器端呈现。
为了比较,here 是在 NodeJS 上使用 Express Web 服务器的解决方案示例,angular 是服务器端渲染的通用解决方案。
我找到了解决办法。
首先,我们需要创建一个组件可以用来设置状态码的可注入服务:
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
文件中添加两行(加上导入语句)(注意这是基于 VS2017 模板创建的股票文件):
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();
});
});
});
});
});
最后我们需要在任何不应该 return 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 dotnet core 的 SPA 项目模板(在 VS2017 和 dotnet core 2.0 中可用)开发一个项目。
我有一个 Angular 组件可以在用户转到无效 URL 时显示 "Not Found" 消息。
我还启用了服务器端预渲染。当 return 从服务器 "Not Found" 预呈现页面时,我如何使它 return 成为 404 的 HTTP 状态代码?
我发现执行此操作的每个方法都使用 Express 作为后端网络服务器,我无法找到在 aspnet 核心后端执行此操作的任何资源。
感谢您的帮助!
为清楚起见编辑:
我不希望 return 特定 MVC 控制器操作或应用程序错误的 404。
我正在寻找 return 来自特定 Angular2/4 组件的 404,由 Microsoft.AspNetCore.SpaServices 在服务器端呈现。
为了比较,here 是在 NodeJS 上使用 Express Web 服务器的解决方案示例,angular 是服务器端渲染的通用解决方案。
我找到了解决办法。
首先,我们需要创建一个组件可以用来设置状态码的可注入服务:
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
文件中添加两行(加上导入语句)(注意这是基于 VS2017 模板创建的股票文件):
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();
});
});
});
});
});
最后我们需要在任何不应该 return 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);
}
}