Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular not catching error returned from UserFriendlyException #19852

Open
1 task done
zachhongcy opened this issue May 16, 2024 · 3 comments
Open
1 task done

Angular not catching error returned from UserFriendlyException #19852

zachhongcy opened this issue May 16, 2024 · 3 comments

Comments

@zachhongcy
Copy link

Is there an existing issue for this?

  • 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;
        });
@Sinan997
Copy link
Contributor

Hi, can you provide an example project?

@zachhongcy
Copy link
Author

zachhongcy commented Jun 1, 2024

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.

@sumeyyeKurtulus
Copy link
Contributor

sumeyyeKurtulus commented Jun 4, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants