2020/02/01, ASP.NET Core 3.1, VS2019
摘要:基於ASP.NET Core 3.1 WebApi搭建后端多層網站架構【11-WebApi統一處理返回值、異常】
使用IExceptionFilter過濾器實現異常統一處理,使用IResultFilter過濾器實現統一處理返回值
本章節介紹了使用IExceptionFilter實現異常統一處理,使用IResultFilter實現統一處理返回值
添加異常過濾器
在MS.WebApi
應用程序中新建Filters文件夾,在該文件夾下新建ApiExceptionFilter.cs
類:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using MS.Component.Aop;
namespace MS.WebApi.Filters
{
/// <summary>
/// api異常過濾器
/// </summary>
public class ApiExceptionFilter : IExceptionFilter
{
private readonly ILogger<ApiExceptionFilter> _logger;
public ApiExceptionFilter(ILogger<ApiExceptionFilter> logger)
{
_logger = logger;
}
public void OnException(ExceptionContext context)
{
string methodInfo = $"{context.RouteData.Values["controller"] as string}Controller.{context.RouteData.Values["action"] as string}:{context.HttpContext.Request.Method}";
//如果不是AopHandledException異常,則可能沒有記錄過日志,進行日志記錄
if (!(context.Exception is AopHandledException))
{
_logger.LogError(context.Exception, "執行{0}時發生錯誤!", methodInfo);
}
context.Result = new JsonResult(new
{
status = 501,
data = "服務器出錯"
});
}
}
}
如果controller在執行過程中遇到錯誤,則會被過濾器捕獲到,如果錯誤已經被LogAop(之前寫的業務層的)處理過,那在ApiExceptionFilter中判斷下就不處理了,最后統一返回501,提示服務器出錯
添加結果過濾器
在Filters文件夾下新建ApiResultFilter.cs
類:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace MS.WebApi.Filters
{
/// <summary>
/// 給api返回結果包一層狀態碼
/// </summary>
public class ApiResultFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.Result != null)
{
if (context.Result is ObjectResult objectResult)
{
if (objectResult.DeclaredType is null) //返回的是IActionResult類型
{
context.Result = new JsonResult(new
{
status = objectResult.StatusCode,
data = objectResult.Value
});
}
else//返回的是string、List這種其他類型,此時沒有statusCode,應盡量使用IActionResult類型
{
context.Result = new JsonResult(new
{
status = 200,
data = objectResult.Value
});
}
}
else if (context.Result is EmptyResult)
{
context.Result = new JsonResult(new
{
status = 200,
data = ""
});
}
else
{
throw new Exception($"未經處理的Result類型:{ context.Result.GetType().Name}");
}
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
}
- 就是對返回值又包了一層,status是狀態碼,data是數據
應用過濾器
Startup.cs
類中,給AddControllers方法添加參數:
services.AddControllers(options =>
{
options.Filters.Add<ApiResultFilter>();
options.Filters.Add<ApiExceptionFilter>();
});
將services.AddControllers();
改成以上內容:
- 這樣做是全局應用,所有的controller都會應用上面兩個過濾器
- 如果只想部分應用,可以考慮使用Attribute類型的過濾器,請查閱官方文檔-篩選器章節
至此,過濾器已應用成功,啟動項目,打開Postman調用接口:
可以看到返回值已經包了一層
項目完成后,如下圖所示