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

ASP.NET MVC控制器中如何全局处理API响应?

API响应统一处理重构方案

完全可以重构代码实现全局统一处理API响应,避免在每个控制器方法中重复编写相似的switch逻辑。结合你已有的BearerTokenHandler类,这里提供两种实用方案:

方案一:利用BearerTokenHandler统一处理响应

BearerTokenHandler作为DelegatingHandler,可以拦截所有通过该Handler的HttpClient请求,在SendAsync方法中统一处理响应状态码,实现全局复用。

修改BearerTokenHandler代码

public class BearerTokenHandler : DelegatingHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BearerTokenHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        var context = _httpContextAccessor.HttpContext;

        // 统一处理各类状态码
        switch (response.StatusCode)
        {
            case HttpStatusCode.Unauthorized:
                // 直接触发重定向到权限拒绝页面
                context?.Response.Redirect("/Account/AccessDenied");
                break;
            case HttpStatusCode.BadRequest:
            case HttpStatusCode.NotFound:
                // 解析错误信息并存入HttpContext,供控制器读取
                var errorMsg = await response.Content.ReadAsStringAsync(cancellationToken);
                context?.Items["ApiError"] = errorMsg;
                break;
            case HttpStatusCode.OK:
                // 成功状态留到控制器中解析业务数据
                break;
            default:
                context?.Items["ApiError"] = $"API请求失败,状态码:{response.StatusCode}";
                break;
        }

        return response;
    }
}

配置DI与控制器使用

  1. 注册依赖到DI容器:
// Program.cs中添加
services.AddHttpContextAccessor();
services.AddHttpClient("ApiClient")
        .AddHttpMessageHandler<BearerTokenHandler>();
  1. 控制器中简化响应处理:
public class YourController : Controller
{
    private readonly HttpClient _httpClient;

    public YourController(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("ApiClient");
    }

    public async Task<IActionResult> YourAction()
    {
        var apiResponse = await _httpClient.PostAsync("api/your-endpoint", new StringContent("请求内容"));

        // 仅处理成功场景,其他状态码已在Handler中处理
        if (apiResponse.IsSuccessStatusCode)
        {
            var data = await apiResponse.Content.ReadFromJsonAsync<YourBusinessModel>();
            return View(data);
        }

        // 从HttpContext读取统一处理的错误信息
        ViewData["Error"] = HttpContext.Items["ApiError"] as string ?? "未知错误";
        return View();
    }
}

方案二:封装独立响应处理服务

如果不想在BearerTokenHandler中耦合MVC页面重定向这类业务逻辑,可以封装一个专门的响应处理服务,将状态码处理逻辑集中管理。

创建ApiResponseHandler服务

public class ApiResponseHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ApiResponseHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<IActionResult> HandleResponseAsync(
        HttpResponseMessage response, 
        Func<Task<IActionResult>> successHandler)
    {
        var context = _httpContextAccessor.HttpContext;
        switch (response.StatusCode)
        {
            case HttpStatusCode.OK:
                return await successHandler();
            case HttpStatusCode.Unauthorized:
                return RedirectToAction("AccessDenied", "Account");
            case HttpStatusCode.BadRequest:
            case HttpStatusCode.NotFound:
                context?.ViewData["Error"] = await response.Content.ReadAsStringAsync();
                return View();
            default:
                context?.ViewData["Error"] = $"请求失败,状态码:{response.StatusCode}";
                return View();
        }
    }
}

控制器中使用服务

public class YourController : Controller
{
    private readonly HttpClient _httpClient;
    private readonly ApiResponseHandler _responseHandler;

    public YourController(IHttpClientFactory httpClientFactory, ApiResponseHandler responseHandler)
    {
        _httpClient = httpClientFactory.CreateClient("ApiClient");
        _responseHandler = responseHandler;
    }

    public async Task<IActionResult> YourAction()
    {
        var apiResponse = await _httpClient.PostAsync("api/your-endpoint", new StringContent("请求内容"));

        // 调用统一处理方法,仅传入成功场景的逻辑
        return await _responseHandler.HandleResponseAsync(apiResponse, async () =>
        {
            var data = await apiResponse.Content.ReadFromJsonAsync<YourBusinessModel>();
            return View(data);
        });
    }
}

方案对比

  • 方案一:适合全局统一拦截处理,所有使用该HttpClient的请求自动生效,代码侵入性最低。
  • 方案二:逻辑更贴近MVC业务,灵活性更高,适合需要针对不同控制器做细微调整的场景。

内容的提问来源于stack exchange,提问作者Gil León

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:50:26