abp icon indicating copy to clipboard operation
abp copied to clipboard

Angular not catching error returned from UserFriendlyException

Open zachhongcy opened this issue 1 year ago • 5 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Description

Hi I'm facing an issue where Angular HTTP error handling as suggested by ABP in https://docs.abp.io/en/abp/latest/UI/Angular/HTTP-Error-Handling does not catch UserFriendlyException thrown by .NET backend server. Any help or advice would be appreciated, thanks!

Reproduction Steps

Throwing UserFriendlyException in C#, e.g. ProductStockInAppService

            var productStockIns = await _productStockInRepository.GetListAsync();

            if (productStockIns.Count < 1)
            {
                throw new UserFriendlyException("There is nothing to export.");
            }

Catching the error in Angular using CustomHttpErrorHandlerService

  canHandle(error: unknown): boolean {
    if (error instanceof HttpErrorResponse) {
      console.log(JSON.stringify(error));
      this.error = error;
      return true;
    }

    return false;
  }

Toast the error message with status code

  execute(): void {
    this.toaster.error(
      this.error.error?.error?.message,
      this.error.status.toString()
    );
  }

Expected behavior

Angular CustomHttpErrorHandlerService should be able to capture response body that's identical to what is produced by swagger UI:

image

Actual behavior

error.error is undefined when shown in log:

{
   "headers":{
      "normalizedNames":{
         
      },
      "lazyUpdate":null
   },
   "status":403,
   "statusText":"OK",
   "url":"https://localhost:44356/api/app/product-stock-in/export",
   "ok":false,
   "name":"HttpErrorResponse",
   "message":"Http failure response for https://localhost:44356/api/app/product-stock-in/export: 403 OK",
   "error":{
      
   }
}

ToasterService does not show error message, but with the correct status code: image

Regression?

No response

Known Workarounds

No response

Version

8.1

User Interface

Angular

Database Provider

EF Core (Default)

Tiered or separate authentication server

Tiered

Operation System

Windows (Default)

Other information

I had also configured AbpExceptionHandlingOptions in ApplicationService module to send exception details to clients:

ApplicationModule.cs

        Configure<AbpExceptionHandlingOptions>(options =>
        {
            options.SendExceptionsDetailsToClients = true;
            options.SendStackTraceToClients = false;
        });

zachhongcy avatar May 16 '24 18:05 zachhongcy

Hi, can you provide an example project?

Sinan997 avatar May 21 '24 07:05 Sinan997

Hi @Sinan997 please find the minimal reproduceable code in this project: https://github.com/zachhongcy/Acme.BookStore

I tested it again and the issue still persists with ABP v8.1.3. I have a simple BookAppService that throws the UserFriendlyException with message and a button in home component that calls the API.

zachhongcy avatar Jun 01 '24 11:06 zachhongcy

Hello, @zachhongcy. For your case, the error response object is reflected like this:

{
    "headers": {
        "normalizedNames": {},
        "lazyUpdate": null
    },
    "status": 403,
    "statusText": "OK",
    "url": "https://localhost:44305/api/app/book",
    "ok": false,
    "name": "HttpErrorResponse",
    "message": "Http failure response for https://localhost:44305/api/app/book: 403 OK",
    "error": "{\"error\":{\"code\":null,\"message\":\"Unable to find book.\",\"details\":null,\"data\":{},\"validationErrors\":null}}"
}

For this reason, the block where we look for the error message would not work.

  execute(): void {
    this.toaster.error(
      this.error.error?.error?.message,
      this.error.status.toString()
    );
  }

You may try customizing the related part as follows:

  // If this service is picked from ErrorHandler, this execute method will be called.
  execute() {
    const messageRegex = /"message":"(?<message>.*?)"/;
    const messageMatch = this.error.error.match(messageRegex);

    let message = 'Bad request!';
    if (messageMatch && messageMatch.groups && messageMatch.groups.message) {
      message = messageMatch.groups.message;
    }

    this.toaster.error(message, this.error.status.toString());
  }

or you can directly use getErrorFromRequestBody function inside error utilities that might be even more suitable.

sumeyyeKurtulus avatar Jun 04 '24 13:06 sumeyyeKurtulus

I'm getting a similar error, where Angular now catches the error as shown below: image

Whereas, the previous versions of ABP before 8, showed up as error confirmation box on the screen. The UserFriendlyException message is not being relayed to the front end at all anymore.

Are there any solutions to get UserFriendlyExceptions to show as message boxes on screen again?

britt-a avatar Jun 10 '24 13:06 britt-a

I am assuming that you have not configured anything additional to show the error in the toast message format. Otherwise, you should not be redirected to such page by configuring the customization especially using the error utilities.

sumeyyeKurtulus avatar Jun 26 '24 13:06 sumeyyeKurtulus