2017-10-16 109 views
1

我正在使用用於dotnet核心(VS2017和dotnet核心2.0中可用的一個)的Angular SPA項目模板的項目。在aspnet core SPA中返回404狀態代碼Angular應用程序

如果用戶轉到無效URL,我有一個Angular組件顯示「未找到」消息。

我也有服務器端預渲染啓用。從服務器返回預渲染的「未找到」頁面時,如何使其返回HTTP狀態代碼404?

我發現要做到這一點的每個方法都使用Express作爲後端Web服務器,但我一直無法在aspnet核心後端上找到任何資源。

感謝您的幫助!


編輯爲清楚:

我不是在尋找到一個特定的MVC控制器操作或應用程序錯誤返回404。

我期待從特定的Angular2/4組件返回404,由服務器端Microsoft.AspNetCore.SpaServices呈現。

作爲比較,here是在NodeJS上使用Express web服務器並在服務器端呈現角度通用的解決方案的示例。

+0

我認爲這將有助於你https://stackoverflow.com/questions/667053/best-way-to-implement -a-404-in-asp-net – sheplu

+0

更好https://stackoverflow.com/questions/37690114/asp-net-core-how-to-return-a-specific-status-代碼和內容不受控制 – Eliseo

+0

感謝您的建議,但這些都不能解決我的問題。他們都在討論從標準的ASP.Net/ASPNet Core應用程序返回404響應,而不是服務器端呈現的Angular組件。爲了清晰我編輯了我的問題。 – Entith

回答

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模板創建的庫存文件):

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

你能不能也請指導如何處理這個基於新的Angular CLI模板爲.net https://github.com/aspnet/JavaScriptServices/issues/1288#issuecomment-346003334。我認爲角部分大部分是相同的,但我無法弄清.net部分。 –

+0

沒有.NET部分,上面的答案都是Angular。它看起來像基於Angular CLI的模板有很大的改變,包括如何構建和引導Angular應用程序。瀏覽模板「Startup.cs」文件中引用的文檔(https://go.microsoft.com/fwlink/?linkid = 864501),看起來您需要添加一個'main.server.ts'文件,該文件與RTM模板中的'boot.server.ts'類似,但它不同於我不知道如何在它內部處理這個問題,我現在也沒有時間嘗試解決它。 – Entith

+0

沒問題,謝謝:) –