ASP.NET Core搭建多層網站架構【11-WebApi統一處理返回值、異常】


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調用接口:

可以看到返回值已經包了一層

項目完成后,如下圖所示


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM