Angular:无法通过HttpResponse返回自定义错误消息

3

我一直在搜索解决方法,并且看到了一些例子,当我们在控制器操作中返回错误文本时,可以使用ActionResult/JsonResult或使用以下HttpRequest方法:

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

我的后端应用程序使用 ASP.NET Core 2.1.1,但是HttpResponse类中缺少.Status属性。

此外,我无法找到任何可以包含自定义错误消息的属性。

我使用中间件类获取异常描述并将其作为JSON传递。

Startup.cs

app.UseMiddleware<ExceptionHandleMiddleware>();

这个类本身

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,如果要捕获错误,则应返回HTTP错误(否则在Angular拦截器中.catch(...)块将不会被触发)。
以下是我的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(...)确实会返回异常信息,但我无法在拦截器的.catch(...)块中提取它。

public handleError = (error: Response) => {

这里是将errorJSON格式输出的结果(请注意,没有显示错误信息“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的 网络 选项卡,我可以看到以下内容:

enter image description here

所以,我似乎无法从 error: Response 中获取此错误文本。

也许,有人知道更好的方法将错误传递给Angular客户端并在那里获取它?

更新1 - 错误处理程序(我只是为了调查错误内容在那里设置断点)

public handleError = (error: Response) => {
    debugger
    return Observable.throw(error)
}

你能展示一下你的错误处理程序吗?通常情况下,使用 error.error 你应该能够获取到响应体。 - David
你确定请求具有所需的“状态”代码吗?我没有看到请求以红色显示,这可能意味着它失败了。请在Chrome的网络选项卡中检查状态代码。 - Ankit Sharma
当然,@David,但现在它几乎缺少任何代码。我现在正在研究error.body.getReader().read().then(...)部分(刚刚发现它)。 - Alex Herman
@David,在你提供的页面上有一个HttpErrorResponse - 它不适用于Angular 6,这个(Response)似乎是新的,而且接口本身可以在lib.dom.d.ts中找到。 - Alex Herman
好的。如果你从 error.error 进行 console.log,你会得到什么? - David
显示剩余5条评论
2个回答

1

我的疏忽。

如果您查看返回的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)
}

就是这样。


我也遇到了同样的问题。我正在使用ASP NET CORE,其中间件设置错误主体,如await context.Response.WriteAsync(result);,其中result是一些json。似乎我在Angular客户端消耗错误时出现了问题:error = {}。你有没有找到更好的Angular方法来解决这个问题?我正在使用v7.x。 - Adam Cox

0

我最终通过实现中间件来拦截 HttpResponse,从 blob 中提取错误,并在 json 中返回消息来解决这个问题。感谢 JaapMosselman 的贡献。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接