新增ApiResultFilterAttribute.cs文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
namespace Athena.Infrastructure.Mvc.Attributes;

/// <summary>
/// API结果统一处理过滤器
/// </summary>
// ReSharper disable once ClassNeverInstantiated.Global
public class ApiResultFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
// 如果数据抛异常了,则直接返回
if (context.Exception != null)
{
base.OnActionExecuted(context);
return;
}

var objectResult = context.Result as ObjectResult;

// 如果状态码不是200,则代表异常
if (objectResult is {StatusCode: { }} && objectResult.StatusCode != 200)
{
var message = HttpStatusCodeHelper.GetDescription((int) objectResult.StatusCode);
context.Result = new ObjectResult(new
{
objectResult.StatusCode,
Message = message,
Success = false
});
// 设置响应状态码
context.HttpContext.Response.StatusCode = (int) objectResult.StatusCode;

base.OnActionExecuted(context);
return;
}

// 获取结果集
var result = objectResult?.Value;

context.Result = new ObjectResult(new
{
context.HttpContext.Response.StatusCode,
Data = result,
Message = "OK",
Success = true
});

base.OnActionExecuted(context);
}
}

新建Extensions.cs扩展类

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace Athena.Infrastructure.Mvc;

public static class Extensions
{
/// <summary>
/// 添加API结果统一处理过滤器
/// </summary>
/// <param name="options"></param>
public static void AddCustomApiResultFilter(this MvcOptions options)
{
options.Filters.Add<ApiResultFilterAttribute>();
}
}

在Program.cs类中全局启用

1
2
3
4
services.AddControllers(options =>
{
options.AddCustomApiResultFilter();
});

示例,某控制器中

定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
///
/// </summary>
[ApiController]
[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = {
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

[HttpGet(Name = "GetWeatherForecast")]
public IActionResult Get()
{
return Ok(Enumerable.Range(1, 5).Select(index => new
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray());
}
}

结果(使用过滤器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"statusCode": 200,
"data": [
{
"date": "2022-07-13T11:34:18.511525+08:00",
"temperatureC": -2,
"summary": "Freezing"
},
{
"date": "2022-07-14T11:34:18.511647+08:00",
"temperatureC": -5,
"summary": "Mild"
},
{
"date": "2022-07-15T11:34:18.511652+08:00",
"temperatureC": 43,
"summary": "Warm"
},
{
"date": "2022-07-16T11:34:18.511652+08:00",
"temperatureC": -7,
"summary": "Freezing"
},
{
"date": "2022-07-17T11:34:18.511652+08:00",
"temperatureC": 39,
"summary": "Sweltering"
}
],
"message": "OK",
"success": true
}

结果(不使用过滤器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[
{
"date": "2022-07-13T11:36:31.81696+08:00",
"temperatureC": -10,
"summary": "Scorching"
},
{
"date": "2022-07-14T11:36:31.817072+08:00",
"temperatureC": 24,
"summary": "Sweltering"
},
{
"date": "2022-07-15T11:36:31.817074+08:00",
"temperatureC": -8,
"summary": "Balmy"
},
{
"date": "2022-07-16T11:36:31.817074+08:00",
"temperatureC": 11,
"summary": "Chilly"
},
{
"date": "2022-07-17T11:36:31.817074+08:00",
"temperatureC": 18,
"summary": "Chilly"
}
]