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
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)
}
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.