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

Asp.net Core中记录数据库异常并响应Ajax错误提示的问题咨询

解决方案

当前问题的核心是:全局异常处理会将所有异常重定向到错误页面,导致Ajax请求无法获取JSON格式的错误响应。要兼顾异常写入数据库和前端错误提示,需要区分请求类型(Ajax/普通页面)并分别处理。


步骤1:修改异常处理逻辑,区分请求类型

在ErrorLogger控制器中,调整异常处理方法,判断当前请求是否为Ajax请求(通过X-Requested-With请求头),分别返回JSON或错误页面,同时统一记录异常到数据库:

using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;

public class ErrorLoggerController : Controller
{
    private readonly YourDbContext _dbContext;

    // 注入你的数据库上下文
    public ErrorLoggerController(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [AllowAnonymous]
    public IActionResult Index()
    {
        var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        var exception = exceptionFeature?.Error;

        // 1. 统一将异常写入数据库
        LogExceptionToDb(exception);

        // 2. 判断是否为Ajax请求
        if (Request.Headers["X-Requested-With"] == "XMLHttpRequest")
        {
            return Json(new 
            { 
                success = false, 
                message = exception?.Message ?? "服务器发生未知错误" 
            });
        }
        // 普通页面请求返回错误视图
        return View("Error", exception);
    }

    [AllowAnonymous]
    public IActionResult GError(int statusCode)
    {
        var statusFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
        
        // 记录状态码错误到数据库(可选)
        LogStatusCodeErrorToDb(statusCode, statusFeature);

        if (Request.Headers["X-Requested-With"] == "XMLHttpRequest")
        {
            var errorMsg = statusCode switch
            {
                404 => "请求的资源不存在",
                403 => "无权限访问该资源",
                500 => "服务器内部错误",
                _ => $"服务器返回错误状态码:{statusCode}"
            };
            return Json(new { success = false, message = errorMsg });
        }
        return View("StatusCodeError", statusCode);
    }

    // 异常写入数据库的核心逻辑
    private void LogExceptionToDb(Exception ex)
    {
        if (ex == null) return;
        
        var errorLog = new ErrorLog
        {
            Message = ex.Message,
            StackTrace = ex.StackTrace,
            RequestPath = HttpContext.Request.Path,
            RequestMethod = HttpContext.Request.Method,
            CreatedTime = DateTime.Now
        };
        
        _dbContext.ErrorLogs.Add(errorLog);
        _dbContext.SaveChanges();
    }

    // 状态码错误写入数据库的逻辑(可选)
    private void LogStatusCodeErrorToDb(int statusCode, IStatusCodeReExecuteFeature feature)
    {
        var statusLog = new StatusCodeLog
        {
            StatusCode = statusCode,
            OriginalPath = feature?.OriginalPath,
            CreatedTime = DateTime.Now
        };
        
        _dbContext.StatusCodeLogs.Add(statusLog);
        _dbContext.SaveChanges();
    }
}

步骤2:调整前端Ajax代码,处理错误响应

jQuery的Ajax在服务器返回非200状态码时,会进入error回调,需要添加该回调来解析JSON错误信息:

$.ajax({
    type: "POST",
    url: '/ad/locfiles/clf?lfId=' + id,
    success: function (data) {
        if (data.success) {
            toastr.success(data.message);
            dt.ajax.reload();
        } else {
            toastr.error(data.message);
        }
    },
    error: function(xhr, status, error) {
        // 解析服务器返回的JSON错误信息
        var errorData = JSON.parse(xhr.responseText);
        toastr.error(errorData.message);
    }
});

可选:自定义异常中间件(更灵活)

如果需要更精细的控制,可以自定义异常中间件替代全局UseExceptionHandler,直接在中间件中完成异常记录和响应处理:

public class ExceptionLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly YourDbContext _dbContext;

    public ExceptionLoggingMiddleware(RequestDelegate next, YourDbContext dbContext)
    {
        _next = next;
        _dbContext = dbContext;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            // 记录异常到数据库
            await LogExceptionAsync(ex, context);

            // 处理Ajax请求
            if (context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
            {
                context.Response.ContentType = "application/json";
                context.Response.StatusCode = StatusCodes.Status500InternalServerError;
                await context.Response.WriteAsJsonAsync(new 
                { 
                    success = false, 
                    message = ex.Message 
                });
            }
            // 普通页面请求重定向到错误页
            else
            {
                context.Response.Redirect("/ErrorLogger/Index");
            }
        }
    }

    private async Task LogExceptionAsync(Exception ex, HttpContext context)
    {
        var errorLog = new ErrorLog
        {
            Message = ex.Message,
            StackTrace = ex.StackTrace,
            RequestPath = context.Request.Path,
            RequestMethod = context.Request.Method,
            CreatedTime = DateTime.Now
        };
        _dbContext.ErrorLogs.Add(errorLog);
        await _dbContext.SaveChangesAsync();
    }
}

// 在Program.cs中注册中间件(注意顺序:放在UseRouting之前)
app.UseMiddleware<ExceptionLoggingMiddleware>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:45:38