You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core Web API中使用Flurl的OnError检查自定义响应头问题

问题根因分析

    1. OnError事件触发逻辑限制:Flurl默认仅在响应状态码≥400时才会触发OnError相关事件,若对接系统返回200等成功状态码但在头中携带错误信息,你的处理逻辑根本不会执行。
    1. 双处理器冲突:你同时为OnErrorAsync和OnError赋值,Flurl运行时只会执行其中一个处理器,可能导致异步逻辑未正确运行。
    1. 响应对象未完全更新:你仅修改了FlurlCall.HttpResponseMessage属性,但Flurl上层调用常用的IFlurlResponse相关缓存属性没有同步更新,会导致上层拿到的还是原始响应。
    1. 解码逻辑无异常捕获:Base64解码、JSON反序列化、Split("\"")[1]索引取值的逻辑都可能抛出未处理异常,一旦异常触发会直接中断自定义处理流程,回到Flurl默认逻辑。
    1. ExceptionHandled设置错误:你设置了ExceptionHandled = false,Flurl会继续抛出FlurlHttpException,若上层代码未正确捕获该异常,中间件的全局异常处理可能直接返回空的204响应。

修复方案

  1. 替换OnError事件为全局AfterCallAsync拦截器,不管响应状态码是什么都优先检查自定义错误头。
  2. 移除同步OnError处理器的配置,仅保留异步实现。
  3. 为解码逻辑添加异常捕获,避免处理流程中断。
  4. 优化错误消息提取逻辑,避免索引越界。
  5. 同步更新FlurlCall的相关属性,根据业务需要决定是否吞掉异常。

修正后代码示例

处理逻辑

/// <summary>
/// 全局拦截响应,检查自定义错误消息头并替换响应内容
/// </summary>
public static async Task HandleCustomErrorHeaderAsync(FlurlCall call)
{
    try
    {
        // 不管状态码,先检查是否存在自定义错误头
        if (call.Response?.Headers.TryGetFirst("Messages", out var message) == true)
        {
            // 解码消息
            var messageBytes = Convert.FromBase64String(message);
            var decodedMessage = JsonSerializer.Deserialize<Message>(Encoding.UTF8.GetString(messageBytes));
            
            // 安全提取错误消息
            string errorMsg = null;
            if (decodedMessage?.RawMessage != null)
            {
                var parts = decodedMessage.RawMessage.Split('"');
                if (parts.Length >= 2)
                {
                    errorMsg = parts[1];
                }
            }
            errorMsg ??= await call.Response.GetStringAsync();

            // 构造新的响应
            var newResponse = new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                RequestMessage = call.HttpRequestMessage,
                Content = new StringContent(errorMsg, System.Text.Encoding.UTF8, "application/json")
            };

            // 同步更新FlurlCall所有关联的响应属性
            call.HttpResponseMessage = newResponse;
            call.Response = new FlurlResponse(newResponse);
            // 若不需要Flurl抛出异常,设置ExceptionHandled = true
            call.ExceptionHandled = true;
        }
    }
    catch (Exception ex)
    {
        // 自定义处理逻辑出错时不要影响原有响应流程,可在这里添加日志记录
        System.Diagnostics.Debug.WriteLine($"处理自定义错误头失败:{ex.Message}");
    }
}

Flurl配置

FlurlHttp.Configure(settings =>
{
    // 只保留异步拦截器,替换原有OnError配置
    settings.AfterCallAsync = HandleCustomErrorHeaderAsync;
    // 其他原有配置保留即可
});

内容的提问来源于stack exchange,提问作者thebugsdontwork

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 18:00:01