P0 实现全局异常处理中间件:移除所有Controller重复try-catch,统一异常响应

This commit is contained in:
claw_bot 2026-03-11 07:56:58 +00:00
parent 949fa8e85b
commit 89244fc078
3 changed files with 385 additions and 414 deletions

View File

@ -52,88 +52,74 @@ public class PortfolioController : ControllerBase
[HttpPost]
public ActionResult<ApiResponse<CreatePortfolioResponse>> CreatePortfolio([FromBody] CreatePortfolioRequest request)
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<CreatePortfolioResponse>
{
return Unauthorized(new ApiResponse<CreatePortfolioResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation("Request to create portfolio");
_logger.LogInformation("Request to create portfolio");
// 1. 获取用户默认币种
var db = _databaseService.GetDb();
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
if (user == null)
// 1. 获取用户默认币种
var db = _databaseService.GetDb();
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
if (user == null)
{
return NotFound(new ApiResponse<CreatePortfolioResponse>
{
return NotFound(new ApiResponse<CreatePortfolioResponse>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "用户不存在"
});
}
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "用户不存在"
});
}
// 2. 校验组合币种,如果没传则用用户默认币种
if (string.IsNullOrEmpty(request.currency))
// 2. 校验组合币种,如果没传则用用户默认币种
if (string.IsNullOrEmpty(request.currency))
{
request.currency = user.DefaultCurrency;
}
if (!CurrencyHelper.IsSupported(request.currency))
{
return BadRequest(new ApiResponse<CreatePortfolioResponse>
{
request.currency = user.DefaultCurrency;
}
if (!CurrencyHelper.IsSupported(request.currency))
{
return BadRequest(new ApiResponse<CreatePortfolioResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的组合币种: {request.currency},支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}"
});
}
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的组合币种: {request.currency},支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}"
});
}
// 3. 校验持仓币种
if (request.stocks != null)
// 3. 校验持仓币种
if (request.stocks != null)
{
foreach (var stock in request.stocks)
{
foreach (var stock in request.stocks)
if (!string.IsNullOrEmpty(stock.currency) && !CurrencyHelper.IsSupported(stock.currency))
{
if (!string.IsNullOrEmpty(stock.currency) && !CurrencyHelper.IsSupported(stock.currency))
return BadRequest(new ApiResponse<CreatePortfolioResponse>
{
return BadRequest(new ApiResponse<CreatePortfolioResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的持仓币种: {stock.currency}(标的: {stock.code}),支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}"
});
}
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的持仓币种: {stock.currency}(标的: {stock.code}),支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}"
});
}
}
var response = _portfolioService.CreatePortfolio(request, userId);
}
var response = _portfolioService.CreatePortfolio(request, userId);
_logger.LogInformation("Portfolio created successfully");
return Ok(new ApiResponse<CreatePortfolioResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
_logger.LogInformation("Portfolio created successfully");
return Ok(new ApiResponse<CreatePortfolioResponse>
{
_logger.LogError(ex, "Error creating portfolio");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<CreatePortfolioResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
data = null,
message = ex.Message
});
}
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
/// <summary>
@ -143,43 +129,29 @@ public class PortfolioController : ControllerBase
[HttpGet]
public ActionResult<ApiResponse<GetPortfoliosResponse>> GetPortfolios()
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<GetPortfoliosResponse>
{
return Unauthorized(new ApiResponse<GetPortfoliosResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation("Request to get portfolios");
var response = _portfolioService.GetPortfolios(userId);
_logger.LogInformation("Portfolios retrieved successfully");
return Ok(new ApiResponse<GetPortfoliosResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = new GetPortfoliosResponse { items = response },
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving portfolios");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<GetPortfoliosResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = ex.Message
message = "用户未授权"
});
}
_logger.LogInformation("Request to get portfolios");
var response = _portfolioService.GetPortfolios(userId);
_logger.LogInformation("Portfolios retrieved successfully");
return Ok(new ApiResponse<GetPortfoliosResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = new GetPortfoliosResponse { items = response },
message = "success"
});
}
/// <summary>
@ -189,43 +161,29 @@ public class PortfolioController : ControllerBase
[HttpGet("assets")]
public ActionResult<ApiResponse<TotalAssetsResponse>> GetTotalAssets()
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<TotalAssetsResponse>
{
return Unauthorized(new ApiResponse<TotalAssetsResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation("Request to get total assets");
var response = _portfolioService.GetTotalAssets(userId);
_logger.LogInformation("Total assets retrieved successfully");
return Ok(new ApiResponse<TotalAssetsResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving total assets");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<TotalAssetsResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = ex.Message
message = "用户未授权"
});
}
_logger.LogInformation("Request to get total assets");
var response = _portfolioService.GetTotalAssets(userId);
_logger.LogInformation("Total assets retrieved successfully");
return Ok(new ApiResponse<TotalAssetsResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
/// <summary>
@ -236,43 +194,29 @@ public class PortfolioController : ControllerBase
[HttpGet("{id}")]
public async Task<ActionResult<ApiResponse<PortfolioDetailResponse>>> GetPortfolioById(string id)
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<PortfolioDetailResponse>
{
return Unauthorized(new ApiResponse<PortfolioDetailResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation($"Request to get portfolio by id: {id}");
var response = await _portfolioService.GetPortfolioByIdAsync(id, userId);
_logger.LogInformation("Portfolio retrieved successfully");
return Ok(new ApiResponse<PortfolioDetailResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving portfolio");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<PortfolioDetailResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = ex.Message
message = "用户未授权"
});
}
_logger.LogInformation($"Request to get portfolio by id: {id}");
var response = await _portfolioService.GetPortfolioByIdAsync(id, userId);
_logger.LogInformation("Portfolio retrieved successfully");
return Ok(new ApiResponse<PortfolioDetailResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
/// <summary>
@ -285,43 +229,29 @@ public class PortfolioController : ControllerBase
[HttpGet("transactions")]
public ActionResult<ApiResponse<GetTransactionsResponse>> GetTransactions([FromQuery] string portfolioId, [FromQuery] int limit = 10, [FromQuery] int offset = 0)
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<GetTransactionsResponse>
{
return Unauthorized(new ApiResponse<GetTransactionsResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation($"Request to get transactions for portfolio: {portfolioId}");
var response = _portfolioService.GetTransactions(portfolioId, userId, limit, offset);
_logger.LogInformation("Transactions retrieved successfully");
return Ok(new ApiResponse<GetTransactionsResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving transactions");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<GetTransactionsResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = ex.Message
message = "用户未授权"
});
}
_logger.LogInformation($"Request to get transactions for portfolio: {portfolioId}");
var response = _portfolioService.GetTransactions(portfolioId, userId, limit, offset);
_logger.LogInformation("Transactions retrieved successfully");
return Ok(new ApiResponse<GetTransactionsResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
/// <summary>
@ -332,90 +262,76 @@ public class PortfolioController : ControllerBase
[HttpPost("transactions")]
public ActionResult<ApiResponse<CreateTransactionResponse>> CreateTransaction([FromBody] CreateTransactionRequest request)
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<CreateTransactionResponse>
{
return Unauthorized(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation("Request to create transaction");
// 校验交易币种
if (!string.IsNullOrEmpty(request.currency) && !CurrencyHelper.IsSupported(request.currency))
{
return BadRequest(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的交易币种: {request.currency},支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}"
});
}
// 校验交易币种必须和组合本位币一致
var portfolio = _databaseService.GetDb().Queryable<Portfolio>().Where(p => p.Id == request.portfolioId && p.UserId == userId).First();
if (portfolio == null)
{
return NotFound(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "投资组合不存在"
});
}
if (!string.IsNullOrEmpty(request.currency) && !request.currency.Equals(portfolio.Currency, StringComparison.OrdinalIgnoreCase))
{
return BadRequest(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"该组合本位币为 {portfolio.Currency},只能添加相同币种的标的"
});
}
// 校验资产类型
if (!string.IsNullOrEmpty(request.assetType))
{
var validAssetTypes = new[] { "Stock", "Crypto" };
if (!validAssetTypes.Contains(request.assetType, StringComparer.OrdinalIgnoreCase))
{
return BadRequest(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的资产类型: {request.assetType},支持的类型: {string.Join(", ", validAssetTypes)}"
});
}
}
var response = _portfolioService.CreateTransaction(request, userId);
_logger.LogInformation("Transaction created successfully");
return Ok(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating transaction");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = ex.Message
message = "用户未授权"
});
}
_logger.LogInformation("Request to create transaction");
// 校验交易币种
if (!string.IsNullOrEmpty(request.currency) && !CurrencyHelper.IsSupported(request.currency))
{
return BadRequest(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的交易币种: {request.currency},支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}"
});
}
// 校验交易币种必须和组合本位币一致
var portfolio = _databaseService.GetDb().Queryable<Portfolio>().Where(p => p.Id == request.portfolioId && p.UserId == userId).First();
if (portfolio == null)
{
return NotFound(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "投资组合不存在"
});
}
if (!string.IsNullOrEmpty(request.currency) && !request.currency.Equals(portfolio.Currency, StringComparison.OrdinalIgnoreCase))
{
return BadRequest(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"该组合本位币为 {portfolio.Currency},只能添加相同币种的标的"
});
}
// 校验资产类型
if (!string.IsNullOrEmpty(request.assetType))
{
var validAssetTypes = new[] { "Stock", "Crypto" };
if (!validAssetTypes.Contains(request.assetType, StringComparer.OrdinalIgnoreCase))
{
return BadRequest(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.BadRequest,
data = null,
message = $"不支持的资产类型: {request.assetType},支持的类型: {string.Join(", ", validAssetTypes)}"
});
}
}
var response = _portfolioService.CreateTransaction(request, userId);
_logger.LogInformation("Transaction created successfully");
return Ok(new ApiResponse<CreateTransactionResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
/// <summary>
@ -426,80 +342,66 @@ public class PortfolioController : ControllerBase
[HttpGet("{id}/signal")]
public async Task<ActionResult<ApiResponse<StrategySignal>>> GetPortfolioSignal(string id)
{
try
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<StrategySignal>
{
return Unauthorized(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "用户未授权"
});
}
_logger.LogInformation("Request to get portfolio signal: {PortfolioId}", id);
// 1. 获取投资组合
var portfolio = _databaseService.GetPortfolioById(id, userId);
if (portfolio == null)
{
return NotFound(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "投资组合不存在"
});
}
// 2. 获取策略
if (portfolio.StrategyId == null)
{
return NotFound(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "策略ID不存在"
});
}
var strategy = _strategyService.GetStrategyById(portfolio.StrategyId, userId);
if (strategy == null)
{
return NotFound(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "策略不存在"
});
}
// 3. 获取持仓
var positions = _databaseService.GetPositionsByPortfolioId(id);
// 4. 计算策略信号
var signal = await _strategyEngine.CalculateSignalAsync(strategy, positions);
_logger.LogInformation("Portfolio signal retrieved successfully: {PortfolioId}", id);
return Ok(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.Success,
data = signal,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting portfolio signal: {PortfolioId}", id);
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = ex.Message
message = "用户未授权"
});
}
_logger.LogInformation("Request to get portfolio signal: {PortfolioId}", id);
// 1. 获取投资组合
var portfolio = _databaseService.GetPortfolioById(id, userId);
if (portfolio == null)
{
return NotFound(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "投资组合不存在"
});
}
// 2. 获取策略
if (portfolio.StrategyId == null)
{
return NotFound(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "策略ID不存在"
});
}
var strategy = _strategyService.GetStrategyById(portfolio.StrategyId, userId);
if (strategy == null)
{
return NotFound(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "策略不存在"
});
}
// 3. 获取持仓
var positions = _databaseService.GetPositionsByPortfolioId(id);
// 4. 计算策略信号
var signal = await _strategyEngine.CalculateSignalAsync(strategy, positions);
_logger.LogInformation("Portfolio signal retrieved successfully: {PortfolioId}", id);
return Ok(new ApiResponse<StrategySignal>
{
code = AssetManager.Models.StatusCodes.Success,
data = signal,
message = "success"
});
}
/// <summary>
@ -510,85 +412,71 @@ public class PortfolioController : ControllerBase
[HttpDelete("{id}")]
public async Task<ActionResult<ApiResponse<bool>>> DeletePortfolio(string id)
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = false,
message = "用户未授权"
});
}
_logger.LogInformation($"Request to delete portfolio: {id}");
var db = _databaseService.GetDb();
// 校验组合是否存在且属于当前用户
var portfolio = db.Queryable<Portfolio>()
.Where(p => p.Id == id && p.UserId == userId)
.First();
if (portfolio == null)
{
return NotFound(new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = false,
message = "投资组合不存在或无权限删除"
});
}
// 开启事务删除相关数据
db.Ado.BeginTran();
try
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = false,
message = "用户未授权"
});
}
_logger.LogInformation($"Request to delete portfolio: {id}");
// 删除交易记录
db.Deleteable<Transaction>()
.Where(t => t.PortfolioId == id)
.ExecuteCommand();
var db = _databaseService.GetDb();
// 删除持仓
db.Deleteable<Position>()
.Where(p => p.PortfolioId == id)
.ExecuteCommand();
// 校验组合是否存在且属于当前用户
var portfolio = db.Queryable<Portfolio>()
.Where(p => p.Id == id && p.UserId == userId)
.First();
// 删除组合本身
db.Deleteable<Portfolio>()
.Where(p => p.Id == id)
.ExecuteCommand();
if (portfolio == null)
{
return NotFound(new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = false,
message = "投资组合不存在或无权限删除"
});
}
// 开启事务删除相关数据
db.Ado.BeginTran();
try
{
// 删除交易记录
db.Deleteable<Transaction>()
.Where(t => t.PortfolioId == id)
.ExecuteCommand();
// 删除持仓
db.Deleteable<Position>()
.Where(p => p.PortfolioId == id)
.ExecuteCommand();
// 删除组合本身
db.Deleteable<Portfolio>()
.Where(p => p.Id == id)
.ExecuteCommand();
db.Ado.CommitTran();
}
catch (Exception ex)
{
db.Ado.RollbackTran();
_logger.LogError(ex, "删除投资组合事务失败");
throw;
}
_logger.LogInformation($"Portfolio {id} deleted successfully");
return Ok(new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.Success,
data = true,
message = "删除成功"
});
db.Ado.CommitTran();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting portfolio");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
data = false,
message = ex.Message
});
db.Ado.RollbackTran();
_logger.LogError(ex, "删除投资组合事务失败");
throw;
}
_logger.LogInformation($"Portfolio {id} deleted successfully");
return Ok(new ApiResponse<bool>
{
code = AssetManager.Models.StatusCodes.Success,
data = true,
message = "删除成功"
});
}
}

View File

@ -0,0 +1,80 @@
using AssetManager.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
namespace AssetManager.API.Middleware;
/// <summary>
/// 全局异常处理中间件统一捕获所有API异常返回标准格式响应
/// </summary>
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionMiddleware> _logger;
public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "请求处理异常: {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = new ApiResponse<object>
{
code = StatusCodes.Status500InternalServerError,
data = null,
message = exception.Message
};
// 根据异常类型设置不同的状态码
switch (exception)
{
case UnauthorizedAccessException _:
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
response.code = StatusCodes.Status401Unauthorized;
response.message = "未授权访问";
break;
case ArgumentException _:
case InvalidOperationException _:
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
response.code = StatusCodes.Status400BadRequest;
break;
case KeyNotFoundException _:
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
response.code = StatusCodes.Status404NotFound;
break;
default:
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
response.code = StatusCodes.Status500InternalServerError;
// 生产环境可以隐藏具体错误信息,避免泄露敏感信息
// response.message = "服务器内部错误";
break;
}
var result = JsonSerializer.Serialize(response, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});
return context.Response.WriteAsync(result);
}
}

View File

@ -115,6 +115,9 @@ var app = builder.Build();
// 初始化数据库
app.Services.InitializeDatabase();
// 全局异常处理中间件(必须放在最前面)
app.UseMiddleware<GlobalExceptionMiddleware>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();