问题描述
默认语言是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", "简体中文"));});
