简体   繁体   English

在 Angular 和 .Net Core API 中显示自定义服务器端错误消息

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

I have some rest API written in C# and the API is called from Angular (I am using version Angular 8).我有一些用 C# 编写的其余 API,并且该 API 是从 Angular 调用的(我使用的是 Angular 8 版本)。 The call is fine and it is working fine.通话很好,工作正常。 However, in case of any exception, I cannot display the customized error message in angular.但是,如果出现任何异常,我无法以 angular 显示自定义错误消息。 For example, suppose I have a server side validation in C# which validates if the value of a field matches with the string "abc".例如,假设我在 C# 中有一个服务器端验证,它验证字段的值是否与字符串“abc”匹配。 If it does not match, it will throw an error and in UI (developed in Angular), I want to display the message如果不匹配,则会抛出错误,并且在 UI(用 Angular 开发)中,我想显示消息

"Invalid String Specified". “指定的字符串无效”。

My server side code is as below -我的服务器端代码如下 -

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

The Invalid InvalidStringException class is as below - Invalid InvalidStringException类如下 -

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

When that exception is thrown and caught in server side, it is available as 500 exception but could not print the custom message.当该异常被抛出并在服务器端捕获时,它可以作为 500 异常使用,但无法打印自定义消息。

I am trying following code in Angular -我正在尝试在 Angular 中执行以下代码 -

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

Please suggest how to handle that scenario.请建议如何处理这种情况。

The error object that your Angular app receives should be an instance of HttpErrorResponse您的 Angular 应用程序收到的错误对象应该是HttpErrorResponse的实例

You could do something like this to handle http errors:您可以执行以下操作来处理 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");
}

Are you explicitly catching the InvalidStringException in your .NET API controller and returning the custom message?您是否在 .NET API 控制器中明确捕获InvalidStringException并返回自定义消息? If not, the response will be a generic HTTP 500 'Internal Server Error' response.如果不是,则响应将是通用 HTTP 500“内部服务器错误”响应。 I'd suggest explicitly catching the InvalidStringException in your .NET API controller and returning a 400 response with your custom message eg我建议在您的 .NET API 控制器中明确捕获InvalidStringException并使用您的自定义消息返回 400 响应,例如

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

When the InvalidStringException scenario occurs, This will return a HTTP 400 response with "Invalid String specified" as the response body.InvalidStringException情况发生时,这将返回一个 HTTP 400 响应,其中“指定了无效字符串”作为响应正文。 You should be able to log the error on Angular side as you're currently doing...您应该能够像当前所做的那样在 Angular 端记录错误...

You are throwing an exception which is handled by C# exception handler and it will only return the custom error message specified in that handler.您正在抛出一个由 C# 异常处理程序处理的异常,它只会返回该处理程序中指定的自定义错误消息。

To return a custom message, you need to return with http code like 4xx or 5xx.要返回自定义消息,您需要返回 4xx 或 5xx 等 http 代码。

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

Or you can return with 2xx and you have to parse this subscribe or then method eg或者你可以用 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
    });

If throwing a exception is not really necessary, you can return status code 400 and a message using BadRequest :如果真的没有必要抛出异常,您可以使用BadRequest返回状态代码 400 和一条消息:

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

you can use http interceptor to create general error handler for all http error in angular app,this way you can use alert ,redirect to login page in case token expired ,overwrite the error object and more but you can still access to the error object at the component level by add a callback for observable error.您可以使用http拦截器为angular应用程序中的所有http错误创建通用错误处理程序,这样您就可以使用警报,重定向到登录页面以防令牌过期,覆盖错误对象等等,但您仍然可以访问错误对象通过为可观察错误添加回调来提高组件级别。

Error Handler Service错误处理服务

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

add the Interceptor to Providers in app module将拦截器添加到应用程序模块中的提供者

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

demo 🚀演示🚀

MessageService is related to primeng component library ,you can use your own alert structure MessageService与primeng 组件库相关,你可以使用你自己的alert 结构

As other people have mentioned, you need to catch the exception and convert it to an appropriate HTTP response in your own code.正如其他人所提到的,您需要在自己的代码中捕获异常并将其转换为适当的 HTTP 响应。

The reason for that is because if otherwise your exception is handled by ASP.NET Core using exception handling configuration you have, and it may vary:这样做的原因是因为如果您的异常由 ASP.NET Core 使用您拥有的异常处理配置处理,并且它可能会有所不同:

With developer exception page带有开发者例外页面

Usually in development, you will have code:通常在开发中,你会有代码:

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

What it does is when your environment is Development , it turns on a special page for developers to see information of unhandled exceptions.它的作用是当您的环境为Development 时,它会打开一个特殊页面供开发人员查看未处理异常的信息。 It is only in this case, you get the exception stacktrace as well as the exception message in the response body.只有在这种情况下,您才能在响应正文中获得异常堆栈跟踪以及异常消息。

Without developer exception page无开发者异常页面

Conversely, if the exception page is turned off (usually off for Production environment), you will see nothing in the response body.相反,如果关闭异常页面(通常在生产环境中关闭),您将在响应正文中看不到任何内容

How to fix怎么修

Given exception handling in ASP.NET Core is a cross-cutting concern, I wouldn't use try...catch around everywhere InvalidStringException needs to be converted to HttpResponse .鉴于 ASP.NET Core 中的异常处理是一个跨领域的问题,我不会在任何需要将InvalidStringException转换为HttpResponse地方使用try...catch

I would instead use either an IActionFilter or use UseExceptionHandler which is the exception handling middleware :我会改为使用IActionFilter或使用UseExceptionHandler ,它是异常处理中间件

Here is an example of using UseExceptionHandler in Configure method in Startup.cs :以下是在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);
        }
    }));

In this way, your InvalidStringException is handled globally in your application, without explicit try...catch .这样,您的InvalidStringException在您的应用程序中全局处理,无需显式try...catch And you could throw the exception anywhere in your code, the above code would catch the exception and properly convert it to an HTTP response with your own message as the body.您可以在代码中的任何位置抛出异常,上面的代码将捕获异常并将其正确转换为 HTTP 响应,并将您自己的消息作为正文。

Also note, because you are calling the API from an Angular app, so chances are you might need to set CORS up in your API application if the two applications run from different origins.另请注意,因为您是从 Angular 应用程序调用 API,所以如果这两个应用程序从不同的来源运行,您可能需要在 API 应用程序中设置 CORS

Without CORS, your HTTP request from the Angular app may fail before it can reach your API.如果没有 CORS,来自 Angular 应用程序的 HTTP 请求可能会在到达您的 API 之前失败。 In this case, the status of the HTTP response in your Angular app may be undefined .在这种情况下,您的 Angular 应用程序中 HTTP 响应的状态可能是undefined And in your console, you could see CORS errors.在您的控制台中,您可以看到 CORS 错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Azure 不显示托管 .net 核心 API 的自定义错误消息 - Azure does not display custom error message for hosted .net core API ASP.NET Core 1.0中的服务器端自定义控件呈现 - Server side custom control rendering in ASP.NET Core 1.0 .Net Core 3 web api 的自定义错误对象 - Custom error objects for .Net Core 3 web api ASP.NET 内核 2.2 Web API ZC31C335EF37283C451B18BA0DD317DE1。 托管服务提供商说 500 - 内部服务器错误 - ASP.NET Core 2.2 Web API Angular. Hosting provider says 500 - Internal server error 关于模型验证ASP.NET Core MVC的自定义错误消息 - Custom error message on model validation ASP.NET Core MVC 自定义验证的错误消息未显示asp.net核心 - Error message for custom validation not showing asp.net core .Net Core 自定义身份验证使用 API 密钥和 Identity Server 4 - .Net Core Custom Authentication using API Keys with Identity Server 4 自定义DataAnnotations ValueAttribute在客户端和服务器端验证中提供了不同的错误消息 - Custom DataAnnotations ValueAttribute suppling different error message on client-side and server-side validation Angular 7 和 .NET Core API 中不支持的媒体类型 415 错误 - Unsupported Media Type 415 Error in Angular 7 & .NET Core API 在部署时使用 .NET 核心调用 api Angular Spa 时出错 - Error calling api Angular Spa with .NET Core on deployment
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM