请求参数中字符串转枚举类型失败的问题
在 ASP.NET 8 中的 API 参数中,定义一个枚举参数,从前端传过来的是枚举值字符串,无法自动转化成字符串的问题。并且报错了。我发现在 ASP.NET 5中就没有这个问题,ASP.NET 8 中存在这种问题,具体报错内容如下:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"param": [
"The param field is required."
],
"$.dataScope": [
"The JSON value could not be converted to BY.FusionHub.Common.Enums.DataScopeEnum. Path: $.dataScope | LineNumber: 2 | BytePositionInLine: 20."
]
},
"traceId": "00-1f7814d90e35e0d45e9341f0dd268fb6-9bdb4c3dd7687e02-00"
}
枚举类型:
public enum DataScopeEnum
{
ALL = 0,
CUSTOM = 1,
DEPT = 2,
DEPT_FOLLOW = 3,
USER = 4,
}
API:
[HttpPut("DataScope/{id:int}")]
public async Task<ApiResult> UpdateSystemRole(int id, RolePermissionModel param)
{
return await _systemRoleService.UpdateSystemRolePermission(id, param);
}
Model:
public class RolePermissionModel : BaseModel
{
/// <summary>
/// 数据范围(0:全部数据权限 1:自定数据权限 2:本部门数据权限 3:本部门及以下数据权限 4:仅个人数据权限)
/// </summary>
public DataScopeEnum DataScope { get; set; }
/// <summary>
/// 部门树选择项是否关联显示
/// </summary>
public bool DepartmentCheckStrictly { get; set; } = false;
/// <summary>
/// 部门ID数组
/// </summary>
public int[]? DepartmentList { get; set; }
}
原因
因为在 ASP.NET Core 6.0 以后,默认的 JSON 序列化行为发生了一些变化。ASP.NET Core 8.0 默认使用的是 System.Text.Json
作为 JSON 序列化/反序列化的库,而在 ASP.NET Core 5.0 时,默认使用的是 Newtonsoft.Json
(如果没有显式更改的话)。
System.Text.Json
的枚举序列化行为比 Newtonsoft.Json
更严格。默认情况下,System.Text.Json
会要求枚举值的字符串完全匹配枚举名称(包括大小写)。而在 Newtonsoft.Json
中,它会在某些情况下进行更宽松的匹配(例如,忽略大小写)。
解决办法
方法一
在 System.Text.Json
中,你可以通过设置 JsonSerializerOptions
来启用枚举的大小写不敏感的转换。
修改 Program.cs
或 Startup.cs
中的 AddJsonOptions
配置,启用大小写不敏感的枚举转换:
/// <summary>
/// 添加控制器服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddControllersService(this IServiceCollection services)
{
services.AddControllers() // 添加控制器
.AddJsonOptions(options => // 配置 JSON 转换器
{
// 添加字符串转枚举转换器
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
// 允许尾随逗号
options.JsonSerializerOptions.AllowTrailingCommas = true;
});
return services;
}
方法二
将 JSON 序列化器更改为 Newtonsoft.Json
,在 Program.cs
中注册 Newtonsoft.Json
:
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.Formatting = Formatting.Indented;
});