3

I've been googling the workaround and seen examples when we return error text in controller action as ActionResult/JsonResult or using HttpRequest approach as follows

HttpContext.Current.Response.Status = "error text";

For my back-end app I use ASP.NET Core 2.1.1 and .Status property is missing in HttpResponse class.

Moreover I can't find any properties which could contain my custom error message.

I use middleware class which grabs exception description and passes it as JSON

Startup.cs

app.UseMiddleware<ExceptionHandleMiddleware>();

The class itself

public class ExceptionHandleMiddleware
{
    private readonly RequestDelegate next;

    public ExceptionHandleMiddleware(RequestDelegate next)
    {
        this.next = next ?? throw new ArgumentNullException(nameof(next));
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            context.Response.Clear();
            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;

            await context.Response.WriteAsync(JsonConvert.SerializeObject(new { error = $"{ex.GetType().FullName}: '{ex.Message}'" }));
        }
    }
}

Have a look at the line

context.Response.StatusCode = StatusCodes.Status500InternalServerError;

This is required because in my Angular 6 app I use HttpInterceptor, and in order to catch error you're supposed to return an HTTP error (otherwise the .catch(...) block isn't being triggered in Angular interceptor).

Here's the bit from my Angular app

@Injectable()
export class ErrorHandlerInterceptor implements HttpInterceptor {

    constructor(
        private notify: NgNotify,
    ) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next
            .handle(req)
            .catch(this.handleError)
    }
    ...

Although context.Response.WriteAsync(...) bit does return the exception text, I am unable to extract it in .catch(...) block of the interceptor.

public handleError = (error: Response) => {

Here's error printed as JSON (note that it's lacking the error message saying "Last Entry")

{  
    "headers":{  
       "normalizedNames":{  

       },
       "lazyUpdate":null
    },
    "status":500,
    "statusText":"OK",
    "url":"https://localhost:44305/api/Entry/GetNext?id=11962",
    "ok":false,
    "name":"HttpErrorResponse",
    "message":"Http failure response for https://localhost:44305/api/Entry/GetNext?id=11962: 500 OK",
    "error":{  

    }
 }

Nevertheless, if I open chrome's Network tab I can see the following

enter image description here

So, I can't seem to fetch this error text from error: Response.

Perhaps, someone knows a better way of passing error to Angular client and fetching it there?

Update 1 - error handler (I've only put the breakpoint there in order to investigate the error's content)

public handleError = (error: Response) => {
    debugger
    return Observable.throw(error)
}
10
  • Can you show your error handler? Normally, with error.error you should be able to get the body Commented Jul 26, 2018 at 14:46
  • Are you sure the request has the required status code? I could not see the request in red colour which could signify that it failed. Please check the status code in Chrome's network tab. Commented Jul 26, 2018 at 14:48
  • certainly @David , but for now it is almost lacking any code. I'm now looking into error.body.getReader().read().then(...) part (...have just discovered it) Commented Jul 26, 2018 at 15:01
  • I'm a bit confused. Response is from the old Http client, isn't it? Have a look there, it might help angular.io/guide/http#getting-error-details Commented Jul 26, 2018 at 15:04
  • @David on the page you've provided there's HttpErrorResponse - it doesn't work with Angular 6, this one (Response) seems to be new, and the interface itself is found in lib.dom.d.ts. Commented Jul 26, 2018 at 15:17

2 Answers 2

1

My oversight.

If you look at the JSON returned

  ....

  "message":"Http failure response for https://localhost:44305/api/Entry/GetNext?id=11962: 500 OK",
  "error":{  

  }
}

error seems to be an empty object

IN FACT error is a Blob which we are supposed to read in the following way

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next
        .handle(req)
        .catch(this.handleError)
}

public handleError = (error: Response) => {

    let reader = new FileReader();

    let ngNotify = this._ngNotify;

    reader.onload = function () {

        var result = JSON.parse(this.result);

        ngNotify.nofity('Error', result.error);
    };

    reader.readAsText(error['error']);

    return Observable.throw(error)
}

And that's it.

Sign up to request clarification or add additional context in comments.

1 Comment

I have this same issue. Using ASP NET CORE with middleware that sets error body like await context.Response.WriteAsync(result); where result is some json. Seems I have issue on the Angular client side to consume the error: error = { }. Did you ever refine this or find a more Angular way? I am using v7.x
0

I eventually solve this by implementing middle-ware to intercept the HttpResponse, extract error from blob, and return the message in the json. Thanks to JaapMosselman's contribution.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.