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

.NET 6 Web API项目如何处理运行时异常,避免生产环境崩溃?

ASP.NET Core 6 Web API 生产环境异常处理方案

针对你的问题,下面是一套能避免应用崩溃、规范异常处理的实操方案:

1. 全局异常中间件兜底,杜绝未处理异常崩溃

全局中间件是最后一道防线,必须放在所有中间件最前面,确保任何未被捕获的异常都会被拦截,不会导致应用直接挂掉。

var builder = WebApplication.CreateBuilder(args);
// 注册你的服务(数据库、日志等)

var app = builder.Build();

// 全局异常处理中间件,必须放在最前面
app.Use(async (context, next) =>
{
    try
    {
        await next();
    }
    catch (Exception ex)
    {
        // 用ILogger记录完整异常信息(包括堆栈),方便后续排查
        var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "未处理的全局异常");

        // 生产环境返回通用500响应,绝对不能暴露异常细节
        context.Response.StatusCode = StatusCodes.Status500InternalServerError;
        context.Response.ContentType = "application/json";
        await context.Response.WriteAsJsonAsync(new
        {
            StatusCode = 500,
            Message = "服务器内部错误,请稍后重试"
        });
    }
});

// 后续中间件按正常顺序添加:UseRouting、UseAuthorization等
app.MapControllers();

app.Run();

2. 针对性搞定类型冲突/转换异常

你遇到的InvalidCastException、FormatException这类运行时异常,要提前拦截,不能等到全局中间件处理:

方案一:用Action过滤器拦截控制器内的类型异常

写一个过滤器专门处理控制器层面的类型相关异常,同时提前校验参数:

public class TypeValidationFilter : IActionFilter, IOrderedFilter
{
    private readonly ILogger<TypeValidationFilter> _logger;

    public TypeValidationFilter(ILogger<TypeValidationFilter> logger)
    {
        _logger = logger;
    }

    // 执行动作前验证参数类型
    public void OnActionExecuting(ActionExecutingContext context)
    {
        foreach (var (paramName, paramValue) in context.ActionArguments)
        {
            var paramDescriptor = context.ActionDescriptor.Parameters.First(p => p.Name == paramName);
            // 检查参数是否匹配预期类型,避免后续转换报错
            if (paramValue != null && paramValue.GetType() != paramDescriptor.ParameterType)
            {
                context.ModelState.AddModelError(paramName, $"参数{paramName}类型错误,预期{paramDescriptor.ParameterType.Name}");
                context.Result = new UnprocessableEntityObjectResult(context.ModelState);
            }
        }
    }

    // 执行动作后捕获类型异常
    public void OnActionExecuted(ActionExecutedContext context)
    {
        if (context.Exception is InvalidCastException || context.Exception is FormatException)
        {
            _logger.LogError(context.Exception, "类型转换异常");
            context.Result = new UnprocessableEntityObjectResult(new
            {
                StatusCode = 422,
                Message = "请求参数类型错误,请检查输入格式"
            });
            context.ExceptionHandled = true; // 标记异常已处理,不会再往上抛
        }
    }
}

然后在Program.cs注册这个过滤器:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<TypeValidationFilter>();
});

方案二:业务代码里做防御性校验

在进行类型转换前,先用安全的方法验证,比如:

// 代替直接Convert.ToInt32,避免抛出FormatException
if (!int.TryParse(inputStr, out var intValue))
{
    throw new FormatException("输入不是有效的整数");
}

// 类型转换前先检查类型,避免InvalidCastException
if (obj is not UserModel user)
{
    throw new InvalidCastException("对象无法转换为UserModel类型");
}

3. 规范已知异常的处理

把业务场景里的已知异常(NotFound、Unauthorized、参数错误等)封装成自定义异常,统一处理成对应HTTP状态码:

定义自定义异常

public class NotFoundException : Exception
{
    public NotFoundException(string message) : base(message) { }
}

public class UnauthorizedException : Exception
{
    public UnauthorizedException(string message) : base(message) { }
}

在过滤器里捕获自定义异常

扩展之前的TypeValidationFilter,加上自定义异常的处理:

public void OnActionExecuted(ActionExecutedContext context)
{
    // 类型异常处理...

    if (context.Exception is NotFoundException notFoundEx)
    {
        context.Result = new NotFoundObjectResult(new
        {
            StatusCode = 404,
            Message = notFoundEx.Message
        });
        context.ExceptionHandled = true;
    }
    else if (context.Exception is UnauthorizedException authEx)
    {
        context.Result = new ObjectResult(new
        {
            StatusCode = 403,
            Message = authEx.Message
        }) { StatusCode = StatusCodes.Status403Forbidden };
        context.ExceptionHandled = true;
    }
}

4. 生产环境必做配置

  • 关闭开发者异常页:绝对不能在生产环境开启,避免泄露敏感代码信息
    if (app.Environment.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    // 生产环境用全局异常中间件即可
    
  • 完善日志:用ILogger或者Serilog等框架,记录异常的完整上下文(请求路径、参数、堆栈),方便排查问题
  • 禁止直接抛出系统级异常:比如NullReferenceException,这类异常要通过代码判空等方式避免,而不是靠异常捕获

5. 核心原则:避免崩溃的关键

  • 所有执行入口(控制器方法、后台任务、定时任务)都要有异常捕获机制,要么局部try-catch,要么交给全局中间件
  • 做防御性编程:对所有外部输入、第三方调用、数据库返回都做合法性校验,从源头减少异常
  • 测试覆盖边界场景:比如输入非法类型、空值、超出范围的数值,确保异常被正确拦截处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:30:54