From 89244fc078ec7f4831c997c048f55ec6a4915438 Mon Sep 17 00:00:00 2001 From: claw_bot Date: Wed, 11 Mar 2026 07:56:58 +0000 Subject: [PATCH] =?UTF-8?q?P0=20=E5=AE=9E=E7=8E=B0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E4=B8=AD=E9=97=B4=E4=BB=B6?= =?UTF-8?q?=EF=BC=9A=E7=A7=BB=E9=99=A4=E6=89=80=E6=9C=89Controller?= =?UTF-8?q?=E9=87=8D=E5=A4=8Dtry-catch=EF=BC=8C=E7=BB=9F=E4=B8=80=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=93=8D=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/PortfolioController.cs | 716 ++++++++---------- .../Middleware/GlobalExceptionMiddleware.cs | 80 ++ AssetManager.API/Program.cs | 3 + 3 files changed, 385 insertions(+), 414 deletions(-) create mode 100644 AssetManager.API/Middleware/GlobalExceptionMiddleware.cs diff --git a/AssetManager.API/Controllers/PortfolioController.cs b/AssetManager.API/Controllers/PortfolioController.cs index 5b64834..d735500 100644 --- a/AssetManager.API/Controllers/PortfolioController.cs +++ b/AssetManager.API/Controllers/PortfolioController.cs @@ -52,88 +52,74 @@ public class PortfolioController : ControllerBase [HttpPost] public ActionResult> CreatePortfolio([FromBody] CreatePortfolioRequest request) { - try + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) + return Unauthorized(new ApiResponse { - return Unauthorized(new ApiResponse - { - 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().Where(u => u.Id == userId).First(); - if (user == null) + // 1. 获取用户默认币种 + var db = _databaseService.GetDb(); + var user = db.Queryable().Where(u => u.Id == userId).First(); + if (user == null) + { + return NotFound(new ApiResponse { - return NotFound(new ApiResponse - { - 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 { - request.currency = user.DefaultCurrency; - } - if (!CurrencyHelper.IsSupported(request.currency)) - { - return BadRequest(new ApiResponse - { - 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 { - return BadRequest(new ApiResponse - { - 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 - { - code = AssetManager.Models.StatusCodes.Success, - data = response, - message = "success" - }); - } - catch (Exception ex) + _logger.LogInformation("Portfolio created successfully"); + + return Ok(new ApiResponse { - _logger.LogError(ex, "Error creating portfolio"); - - return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse - { - code = AssetManager.Models.StatusCodes.InternalServerError, - data = null, - message = ex.Message - }); - } + code = AssetManager.Models.StatusCodes.Success, + data = response, + message = "success" + }); } /// @@ -143,43 +129,29 @@ public class PortfolioController : ControllerBase [HttpGet] public ActionResult> GetPortfolios() { - try + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) + return Unauthorized(new ApiResponse { - return Unauthorized(new ApiResponse - { - 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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = new GetPortfoliosResponse { items = response }, + message = "success" + }); } /// @@ -189,43 +161,29 @@ public class PortfolioController : ControllerBase [HttpGet("assets")] public ActionResult> GetTotalAssets() { - try + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) + return Unauthorized(new ApiResponse { - return Unauthorized(new ApiResponse - { - 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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = response, + message = "success" + }); } /// @@ -236,43 +194,29 @@ public class PortfolioController : ControllerBase [HttpGet("{id}")] public async Task>> GetPortfolioById(string id) { - try + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) + return Unauthorized(new ApiResponse { - return Unauthorized(new ApiResponse - { - 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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = response, + message = "success" + }); } /// @@ -285,43 +229,29 @@ public class PortfolioController : ControllerBase [HttpGet("transactions")] public ActionResult> 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 { - return Unauthorized(new ApiResponse - { - 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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = response, + message = "success" + }); } /// @@ -332,90 +262,76 @@ public class PortfolioController : ControllerBase [HttpPost("transactions")] public ActionResult> CreateTransaction([FromBody] CreateTransactionRequest request) { - try + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) + return Unauthorized(new ApiResponse { - return Unauthorized(new ApiResponse - { - 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 - { - code = AssetManager.Models.StatusCodes.BadRequest, - data = null, - message = $"不支持的交易币种: {request.currency},支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}" - }); - } - - // 校验交易币种必须和组合本位币一致 - var portfolio = _databaseService.GetDb().Queryable().Where(p => p.Id == request.portfolioId && p.UserId == userId).First(); - if (portfolio == null) - { - return NotFound(new ApiResponse - { - code = AssetManager.Models.StatusCodes.NotFound, - data = null, - message = "投资组合不存在" - }); - } - if (!string.IsNullOrEmpty(request.currency) && !request.currency.Equals(portfolio.Currency, StringComparison.OrdinalIgnoreCase)) - { - return BadRequest(new ApiResponse - { - 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 - { - 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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.BadRequest, + data = null, + message = $"不支持的交易币种: {request.currency},支持的币种: {string.Join(", ", CurrencyHelper.GetSupportedCurrencies())}" + }); + } + + // 校验交易币种必须和组合本位币一致 + var portfolio = _databaseService.GetDb().Queryable().Where(p => p.Id == request.portfolioId && p.UserId == userId).First(); + if (portfolio == null) + { + return NotFound(new ApiResponse + { + code = AssetManager.Models.StatusCodes.NotFound, + data = null, + message = "投资组合不存在" + }); + } + if (!string.IsNullOrEmpty(request.currency) && !request.currency.Equals(portfolio.Currency, StringComparison.OrdinalIgnoreCase)) + { + return BadRequest(new ApiResponse + { + 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 + { + 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = response, + message = "success" + }); } /// @@ -426,80 +342,66 @@ public class PortfolioController : ControllerBase [HttpGet("{id}/signal")] public async Task>> GetPortfolioSignal(string id) { - try + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) + return Unauthorized(new ApiResponse { - return Unauthorized(new ApiResponse - { - 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 - { - code = AssetManager.Models.StatusCodes.NotFound, - data = null, - message = "投资组合不存在" - }); - } - - // 2. 获取策略 - if (portfolio.StrategyId == null) - { - return NotFound(new ApiResponse - { - code = AssetManager.Models.StatusCodes.NotFound, - data = null, - message = "策略ID不存在" - }); - } - var strategy = _strategyService.GetStrategyById(portfolio.StrategyId, userId); - if (strategy == null) - { - return NotFound(new ApiResponse - { - 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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.NotFound, + data = null, + message = "投资组合不存在" + }); + } + + // 2. 获取策略 + if (portfolio.StrategyId == null) + { + return NotFound(new ApiResponse + { + code = AssetManager.Models.StatusCodes.NotFound, + data = null, + message = "策略ID不存在" + }); + } + var strategy = _strategyService.GetStrategyById(portfolio.StrategyId, userId); + if (strategy == null) + { + return NotFound(new ApiResponse + { + 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = signal, + message = "success" + }); } /// @@ -510,85 +412,71 @@ public class PortfolioController : ControllerBase [HttpDelete("{id}")] public async Task>> DeletePortfolio(string id) { + var userId = GetCurrentUserId(); + if (string.IsNullOrEmpty(userId)) + { + return Unauthorized(new ApiResponse + { + code = AssetManager.Models.StatusCodes.Unauthorized, + data = false, + message = "用户未授权" + }); + } + + _logger.LogInformation($"Request to delete portfolio: {id}"); + + var db = _databaseService.GetDb(); + + // 校验组合是否存在且属于当前用户 + var portfolio = db.Queryable() + .Where(p => p.Id == id && p.UserId == userId) + .First(); + + if (portfolio == null) + { + return NotFound(new ApiResponse + { + code = AssetManager.Models.StatusCodes.NotFound, + data = false, + message = "投资组合不存在或无权限删除" + }); + } + + // 开启事务删除相关数据 + db.Ado.BeginTran(); try { - var userId = GetCurrentUserId(); - if (string.IsNullOrEmpty(userId)) - { - return Unauthorized(new ApiResponse - { - code = AssetManager.Models.StatusCodes.Unauthorized, - data = false, - message = "用户未授权" - }); - } - - _logger.LogInformation($"Request to delete portfolio: {id}"); + // 删除交易记录 + db.Deleteable() + .Where(t => t.PortfolioId == id) + .ExecuteCommand(); - var db = _databaseService.GetDb(); + // 删除持仓 + db.Deleteable() + .Where(p => p.PortfolioId == id) + .ExecuteCommand(); - // 校验组合是否存在且属于当前用户 - var portfolio = db.Queryable() - .Where(p => p.Id == id && p.UserId == userId) - .First(); + // 删除组合本身 + db.Deleteable() + .Where(p => p.Id == id) + .ExecuteCommand(); - if (portfolio == null) - { - return NotFound(new ApiResponse - { - code = AssetManager.Models.StatusCodes.NotFound, - data = false, - message = "投资组合不存在或无权限删除" - }); - } - - // 开启事务删除相关数据 - db.Ado.BeginTran(); - try - { - // 删除交易记录 - db.Deleteable() - .Where(t => t.PortfolioId == id) - .ExecuteCommand(); - - // 删除持仓 - db.Deleteable() - .Where(p => p.PortfolioId == id) - .ExecuteCommand(); - - // 删除组合本身 - db.Deleteable() - .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 - { - 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 - { - 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 + { + code = AssetManager.Models.StatusCodes.Success, + data = true, + message = "删除成功" + }); } } diff --git a/AssetManager.API/Middleware/GlobalExceptionMiddleware.cs b/AssetManager.API/Middleware/GlobalExceptionMiddleware.cs new file mode 100644 index 0000000..eb367fb --- /dev/null +++ b/AssetManager.API/Middleware/GlobalExceptionMiddleware.cs @@ -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; + +/// +/// 全局异常处理中间件:统一捕获所有API异常,返回标准格式响应 +/// +public class GlobalExceptionMiddleware +{ + private readonly RequestDelegate _next; + private readonly ILogger _logger; + + public GlobalExceptionMiddleware(RequestDelegate next, ILogger 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 + { + 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); + } +} diff --git a/AssetManager.API/Program.cs b/AssetManager.API/Program.cs index b1fabd0..b564026 100644 --- a/AssetManager.API/Program.cs +++ b/AssetManager.API/Program.cs @@ -115,6 +115,9 @@ var app = builder.Build(); // 初始化数据库 app.Services.InitializeDatabase(); +// 全局异常处理中间件(必须放在最前面) +app.UseMiddleware(); + if (app.Environment.IsDevelopment()) { app.UseSwagger();