Angular:无法通过 HttpResponse return 自定义错误消息
Angular: Cannot return custom error message via HttpResponse
我一直在谷歌搜索变通方法,并看到了当我们 控制器操作 中的错误文本 return 为 ActionResult
/JsonResult
或使用 HttpRequest
方法如下
HttpContext.Current.Response.Status = "error text";
对于我的后端应用程序,我使用 ASP.NET Core 2.1.1
并且 .Status
属性 在 HttpResponse
class.
中丢失
此外,我找不到任何可能包含我的自定义错误消息的属性。
我使用中间件 class 获取异常描述并将其作为 JSON
传递
Startup.cs
app.UseMiddleware<ExceptionHandleMiddleware>();
class本身
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}'" }));
}
}
}
看看行
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
这是必需的,因为在我的 Angular 6 应用程序 中,我使用 HttpInterceptor
,为了捕获错误,您应该 return 一个 HTTP 错误(否则 .catch(...)
块不会在 Angular 拦截器中被触发)。
这是我的 Angular 应用
@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)
}
...
尽管 context.Response.WriteAsync(...)
位 做 return 异常文本,我无法在拦截器的 .catch(...)
块中提取它。
public handleError = (error: Response) => {
这里的 error
打印为 JSON
(请注意它缺少错误消息 "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":{
}
}
然而,如果我打开 chrome 的 网络 选项卡,我可以看到以下内容
所以,我似乎无法从 error: Response
中获取此错误文本。
也许有人知道将错误传递给 Angular 客户端并在那里获取错误的更好方法?
更新 1 - 错误处理程序(我把断点放在那里只是为了调查错误的内容)
public handleError = (error: Response) => {
debugger
return Observable.throw(error)
}
我的疏忽。
如果您查看返回的JSON
....
"message":"Http failure response for https://localhost:44305/api/Entry/GetNext?id=11962: 500 OK",
"error":{
}
}
error
似乎是一个 空对象
事实上 error
是一个 Blob
我们应该按以下方式阅读
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)
}
就是这样。
我最终通过实现中间件来拦截 HttpResponse
、从 blob 中提取错误以及 return json 中的消息来解决这个问题。感谢 JaapMosselman's contribution.
我一直在谷歌搜索变通方法,并看到了当我们 控制器操作 中的错误文本 return 为 ActionResult
/JsonResult
或使用 HttpRequest
方法如下
HttpContext.Current.Response.Status = "error text";
对于我的后端应用程序,我使用 ASP.NET Core 2.1.1
并且 .Status
属性 在 HttpResponse
class.
此外,我找不到任何可能包含我的自定义错误消息的属性。
我使用中间件 class 获取异常描述并将其作为 JSON
Startup.cs
app.UseMiddleware<ExceptionHandleMiddleware>();
class本身
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}'" }));
}
}
}
看看行
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
这是必需的,因为在我的 Angular 6 应用程序 中,我使用 HttpInterceptor
,为了捕获错误,您应该 return 一个 HTTP 错误(否则 .catch(...)
块不会在 Angular 拦截器中被触发)。
这是我的 Angular 应用
@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)
}
...
尽管 context.Response.WriteAsync(...)
位 做 return 异常文本,我无法在拦截器的 .catch(...)
块中提取它。
public handleError = (error: Response) => {
这里的 error
打印为 JSON
(请注意它缺少错误消息 "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":{
}
}
然而,如果我打开 chrome 的 网络 选项卡,我可以看到以下内容
所以,我似乎无法从 error: Response
中获取此错误文本。
也许有人知道将错误传递给 Angular 客户端并在那里获取错误的更好方法?
更新 1 - 错误处理程序(我把断点放在那里只是为了调查错误的内容)
public handleError = (error: Response) => {
debugger
return Observable.throw(error)
}
我的疏忽。
如果您查看返回的JSON
....
"message":"Http failure response for https://localhost:44305/api/Entry/GetNext?id=11962: 500 OK",
"error":{
}
}
error
似乎是一个 空对象
事实上 error
是一个 Blob
我们应该按以下方式阅读
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)
}
就是这样。
我最终通过实现中间件来拦截 HttpResponse
、从 blob 中提取错误以及 return json 中的消息来解决这个问题。感谢 JaapMosselman's contribution.