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

2020/02/01, ASP.NET Core 3.1, VS2019html

摘要:基於ASP.NET Core 3.1 WebApi搭建後端多層網站架構【11-WebApi統一處理返回值、異常】
使用IExceptionFilter過濾器實現異常統一處理,使用IResultFilter過濾器實現統一處理返回值git

文章目錄github

此分支項目代碼後端

本章節介紹了使用IExceptionFilter實現異常統一處理,使用IResultFilter實現統一處理返回值api

添加異常過濾器

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類:mvc

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();改爲以上內容:
spa

  • 這樣作是全局應用,全部的controller都會應用上面兩個過濾器
  • 若是隻想部分應用,能夠考慮使用Attribute類型的過濾器,請查閱官方文檔-篩選器章節

至此,過濾器已應用成功,啓動項目,打開Postman調用接口:

能夠看到返回值已經包了一層

項目完成後,以下圖所示

相關文章
相關標籤/搜索