8
votes

I have a Angular 6 client consuming a REST Api developed with .Net Web Api.

Everything is working except for the error handling. When I try to process the error to react differently to different status codes (404, 403, 409, 500...) I simply can't make it work. The HttpErrorResponse object doesn't have any of the fields it is supposed to (like 'status' or 'error').

I've made a super simple service that reproduces the issue:

Request on the service.ts

 public test(): Observable<any> {
    let url = this.templatesUrl + '/myMethod';
    console.log('GET myMethod ' + url);

    return this.http.get<any>(url)
                      .pipe(catchError(this.handleError));
  }

Error handler (pretty much straight from the official documentation):

 private handleError(error: HttpErrorResponse) {
    console.warn(error);

    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.message}`);
    }
    // return an observable with a user-facing error message
    return throwError('Unexpected error');
  }

Service on the .Net side:

[HttpGet]
[Route("myMethod")]
public IHttpActionResult myDotNetMethod()
{
    return InternalServerError(new Exception("Details about the issue"));
}

The service is called and it returns a status code 500 along with a json object:

The status of the response:

Chrome showing the request

The response header, it is json:

Response header, it is json

The json object:

The json object returned

And what the log shows: no status and pretty much an empty object:

What the log shows, no status and pretty much an empty object

Loosk like the HttpErrorResponse is pretty much empty. But the response from the API was fine, the status code is there and the json object too.

What am I missing?

Update: In case you are wonder what hides behind that "Internal Server Error" that shows in the log (it is just the callstack generated by chrome):

enter image description here

Update 2: Here's the error object under the microscope. It is simply "Internal Server Error". No trace of status or message.

enter image description here

3
try to print whole error object in console and check status and message are there or not. some times it is error.error.status and error.error.message. - ashish pal
Ashish, I'm already printing the error object (first line in handleError). It contains... nothing (check the picture in the updated question). - Gelu
can you set a breakpoint in your error handler method and check the value of the error argument? My guess is that the object passed isnt trully a HttpErrorResponse instance - Jota.Toledo
try console.log once - ashish pal
Jota and Ashish, no luck. Check the updated question, that object is empty :_( - Gelu

3 Answers

12
votes

Solved... the object was empty due to an interceptor. So if something similar is happening to you check those out.

I'm sorry to have wasted everyone's time, I was unaware of the existance of that particular interceptor.

2
votes

I think your problem is how you are throwing the error in .Net. Try this:

var statusCode = HttpStatusCode.InternalServerError;

var response = new HttpResponseMessage(statusCode)
{
    Content = new ObjectContent<object>(
        new
        {
            Message = "Error Message",
            ExceptionMessage = "StackTrace"
        },
        new JsonMediaTypeFormatter())
};

throw new HttpResponseException(response);

Or if it does not work try this: https://stackoverflow.com/a/28589333/8758483

Another good idea is to centralize your error handling by implementing an ErrorHandler in Angular.

import { ErrorHandler } from '@angular/core';

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {  
  handleError(error) {
    // your custom error handling logic    
  }
}

Then you tell Angular you want to use this class instead of the default one by providing it in you NgModule:

@NgModule({   
  providers: [{provide: ErrorHandler, useClass: GlobalErrorHandler}]
})

If you want more detail you can read this article:

0
votes

In the response the property is called "Message" and not "message".