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
相关产品推荐
相关产品推荐

