簡體   English   中英

在 Angular 和 .Net Core API 中顯示自定義服務器端錯誤消息

[英]Displaying Custom Server Side Error Message in Angular and .Net Core API

我有一些用 C# 編寫的其余 API,並且該 API 是從 Angular 調用的(我使用的是 Angular 8 版本)。 通話很好,工作正常。 但是,如果出現任何異常,我無法以 angular 顯示自定義錯誤消息。 例如,假設我在 C# 中有一個服務器端驗證,它驗證字段的值是否與字符串“abc”匹配。 如果不匹配,則會拋出錯誤,並且在 UI(用 Angular 開發)中,我想顯示消息

“指定的字符串無效”。

我的服務器端代碼如下 -

if (headerValues.Equals("abc")) {
    throw new InvalidStringException("Invalid String specified", 999);
}

Invalid InvalidStringException類如下 -

public class InvalidStringException : System.Exception
{
    int status { get; set; }
    public InvalidStringException() { }
    public InvalidStringException(string message, int status) : base(message) {
        this.status = status;
     }
}

當該異常被拋出並在服務器端捕獲時,它可以作為 500 異常使用,但無法打印自定義消息。

我正在嘗試在 Angular 中執行以下代碼 -

} catch (error) {
  console.log("Error Status: ", error.status);
  console.log("Error Status: ", error.message);
}

請建議如何處理這種情況。

您的 Angular 應用程序收到的錯誤對象應該是HttpErrorResponse的實例

您可以執行以下操作來處理 http 錯誤:

if (error instanceof HttpErrorResponse) {
  if (!error.status) {
    console.log(error.message || error.toString());
  } else {
    console.log(`error status : ${error.status} ${error.statusText}`);
    switch (error.status) {
      case 401:
        this.router.navigateByUrl("/login");
        break;
      case 500:
        this.router.navigateByUrl("/login");
        console.log(`redirect to login`);
        break;
    }
  }
} else {
  console.error("Other Errors");
}

您是否在 .NET API 控制器中明確捕獲InvalidStringException並返回自定義消息? 如果不是,則響應將是通用 HTTP 500“內部服務器錯誤”響應。 我建議在您的 .NET API 控制器中明確捕獲InvalidStringException並使用您的自定義消息返回 400 響應,例如

try {
    ...
}
catch (InvalidStringException iex) {
    return BadRequest(iex.message); // iex.message == Invalid String specified
}

InvalidStringException情況發生時,這將返回一個 HTTP 400 響應,其中“指定了無效字符串”作為響應正文。 您應該能夠像當前所做的那樣在 Angular 端記錄錯誤...

您正在拋出一個由 C# 異常處理程序處理的異常,它只會返回該處理程序中指定的自定義錯誤消息。

要返回自定義消息,您需要返回 4xx 或 5xx 等 http 代碼。

new HttpResponseException(Request.CreateErrorResponse(System.Net.HttpStatusCode.Conflict, "Custom Message"));

或者你可以用 2xx 返回,你必須解析這個訂閱或方法,例如

new System.Web.Http.Results.ResponseMessageResult(
                    Request.CreateResponse((HttpStatusCode)227, "Custom Error Message")
                );

this.http.get().toPromise().then((response: any) => {
        if (response.status == 227) {
            return error;
        } else {
            return data;
        }
        return apiResponse;
    }).catch(error => {
        //nothing here
    });

如果真的沒有必要拋出異常,您可以使用BadRequest返回狀態代碼 400 和一條消息:

if (headerValues.Equals("abc")) {
    return BadRequest("Invalid String specified");
}

您可以使用http攔截器為angular應用程序中的所有http錯誤創建通用錯誤處理程序,這樣您就可以使用警報,重定向到登錄頁面以防令牌過期,覆蓋錯誤對象等等,但您仍然可以訪問錯誤對象通過為可觀察錯誤添加回調來提高組件級別。

錯誤處理服務

@Injectable()
export class ErrorHandlerService implements HttpInterceptor {
  constructor(private msgServ: MessageService) {}
  public intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      catchError((err: HttpErrorResponse) => {
        switch (err.status) {
          case 500: {
            this.msgServ.add({
              severity: "error",
              summary: "Error ",
              detail: "Server is gone..💀"
            });

            break;
          }
          case 400: {
            this.msgServ.add({
              severity: "error",
              summary: "Error ",
              detail: "custome error message..."
            });

            break;
          }
          case 401: {
            if (err.message == "invalid_token") {
              // router 👉 navigate to login
            }
            break;
          }

          default: {
            this.msgServ.add({
              severity: "error",
              summary: "Error ",
              detail: err.message
            });
          }
        }

        return throwError(err);
      })
    );
  }
}

將攔截器添加到應用程序模塊中的提供者

@NgModule({
  ....
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: ErrorHandlerService, multi: true },
    MessageService
  ],
  ....
})
export class AppModule {}

演示🚀

MessageService與primeng 組件庫相關,你可以使用你自己的alert 結構

正如其他人所提到的,您需要在自己的代碼中捕獲異常並將其轉換為適當的 HTTP 響應。

這樣做的原因是因為如果您的異常由 ASP.NET Core 使用您擁有的異常處理配置處理,並且它可能會有所不同:

帶有開發者例外頁面

通常在開發中,你會有代碼:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

它的作用是當您的環境為Development 時,它會打開一個特殊頁面供開發人員查看未處理異常的信息。 只有在這種情況下,您才能在響應正文中獲得異常堆棧跟蹤以及異常消息。

無開發者異常頁面

相反,如果關閉異常頁面(通常在生產環境中關閉),您將在響應正文中看不到任何內容

怎么修

鑒於 ASP.NET Core 中的異常處理是一個跨領域的問題,我不會在任何需要將InvalidStringException轉換為HttpResponse地方使用try...catch

我會改為使用IActionFilter或使用UseExceptionHandler ,它是異常處理中間件

以下是在Startup.cs 的Configure方法中使用UseExceptionHandler的示例:

app.UseExceptionHandler(opt => opt.Run(
    async ctx =>
    {
        var feature = ctx.Features.Get<IExceptionHandlerFeature>();
        if (feature.Error is InvalidStringException ex)
        {
            await ctx.Response.WriteAsync(ex.Message);
        }
    }));

這樣,您的InvalidStringException在您的應用程序中全局處理,無需顯式try...catch 您可以在代碼中的任何位置拋出異常,上面的代碼將捕獲異常並將其正確轉換為 HTTP 響應,並將您自己的消息作為正文。

另請注意,因為您是從 Angular 應用程序調用 API,所以如果這兩個應用程序從不同的來源運行,您可能需要在 API 應用程序中設置 CORS

如果沒有 CORS,來自 Angular 應用程序的 HTTP 請求可能會在到達您的 API 之前失敗。 在這種情況下,您的 Angular 應用程序中 HTTP 響應的狀態可能是undefined 在您的控制台中,您可以看到 CORS 錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM