问题描述
默认语言是zh-Hans
,但数据模型验证却是en
。
{
"error": {
"code": null,
"message": "你的请求无效!",
"details": "验证时发现以下错误.\r\n - The field Age must be between 0 and 150.\r\n - The Name field is required.\r\n - The field Name must be a string with a minimum length of 1 and a maximum length of 100.\r\n",
"data": {},
"validationErrors": [
{
"message": "The field Age must be between 0 and 150.",
"members": [
"age"
]
},
{
"message": "The Name field is required.",
"members": [
"name"
]
},
{
"message": "The field Name must be a string with a minimum length of 1 and a maximum length of 100.",
"members": [
"name"
]
}
]
}
}
如何解决
经过查看源码,发现数据模型验证加载本地化是通过AddDataAnnotationsLocalization
这个扩展进行的。
public class AbpAspNetCoreMvcModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// 省略其它代码...
var mvcCoreBuilder = context.Services.AddMvcCore(options =>
{
options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute());
});
context.Services.ExecutePreConfiguredActions(mvcCoreBuilder);
var abpMvcDataAnnotationsLocalizationOptions = context.Services
.ExecutePreConfiguredActions(
new AbpMvcDataAnnotationsLocalizationOptions()
);
context.Services
.AddSingleton<IOptions<AbpMvcDataAnnotationsLocalizationOptions>>(
new OptionsWrapper<AbpMvcDataAnnotationsLocalizationOptions>(
abpMvcDataAnnotationsLocalizationOptions
)
);
var mvcBuilder = context.Services.AddMvc()
.AddDataAnnotationsLocalization(options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
{
// 获取资源
var resourceType = abpMvcDataAnnotationsLocalizationOptions
.AssemblyResources
.GetOrDefault(type.Assembly);
if (resourceType != null)
{
return factory.Create(resourceType);
}
return factory.CreateDefaultOrNull() ??
factory.Create(type);
};
})
.AddViewLocalization(); //TODO: How to configure from the application? Also, consider to move to a UI module since APIs does not care about it.
// 省略其它代码...
}
}
DataAnnotationLocalizerProvider
接受一个Func<Type, IStringLocalizerFactory, IStringLocalizer>
委托。
Abp的逻辑是从AbpMvcDataAnnotationsLocalizationOptions.AssemblyResources
获取默认resourceType
,如果为null
就通过factory
从AbpLocalizationOptions.DefaultResourceType
中获取默认资源,如果都没有就根据传入type
创建,碰巧模块都不符合。
解决方法就是把对应模块的默认资源添加上。同时别忘记AddBaseTypes(typeof(AbpValidationResource))
,因为数据验证本地化资源在AbpValidationResource
已经定义了,直接拿来用就行。
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<BookStoreResource>("en")
.AddBaseTypes(typeof(AbpValidationResource))
.AddVirtualJson("/Localization/BookStore");
options.DefaultResourceType = typeof(BookStoreResource);
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
});