代码之家  ›  专栏  ›  技术社区  ›  Entith

返回aspnet core SPA角度应用程序中的404状态代码

  •  3
  • Entith  · 技术社区  · 7 年前

    我正在使用dotnet core的Angular SPA项目模板(VS2017和dotnet core 2.0中提供的模板)进行一个项目。

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

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

    我发现的每一种方法都使用Express作为后端Web服务器,我还没有找到在aspnet core后端上实现这一点的任何资源。

    谢谢你的帮助!


    为清晰起见,请编辑:

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

    我希望从一个特定的Angular2/4组件返回404,并在服务器端渲染 Microsoft.AspNetCore.SpaServices .

    为了进行比较, here 是使用NodeJS上的Express web server和angular universal进行服务器端渲染的解决方案示例。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Entith    7 年前

    我找到了解决办法。

    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;
      }
    }
    

    providers 主阵列 AppModule 模块:

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

    然后我们需要在我们的 boot.server.ts

    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);
      }
    }