diff --git a/labs/Teacher/Infrastructure/Web/LocalizedValidationAttributeAdapterProvider.cs b/labs/Teacher/Infrastructure/Web/LocalizedValidationAttributeAdapterProvider.cs new file mode 100644 index 00000000..449e0009 --- /dev/null +++ b/labs/Teacher/Infrastructure/Web/LocalizedValidationAttributeAdapterProvider.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc.DataAnnotations; +using Microsoft.Extensions.Localization; +using System.ComponentModel.DataAnnotations; + +namespace Infrastructure.Web +{ + public class LocalizedValidationAttributeAdapterProvider : ValidationAttributeAdapterProvider, IValidationAttributeAdapterProvider + { + public new IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer) + { + new RequiredAttributeAdapter(null, null); + return base.GetAttributeAdapter(attribute, stringLocalizer); + } + } +} \ No newline at end of file diff --git a/labs/Teacher/Infrastructure/Web/LocalizedValidationMetadataProvider.cs b/labs/Teacher/Infrastructure/Web/LocalizedValidationMetadataProvider.cs index d33ad517..807b83a3 100644 --- a/labs/Teacher/Infrastructure/Web/LocalizedValidationMetadataProvider.cs +++ b/labs/Teacher/Infrastructure/Web/LocalizedValidationMetadataProvider.cs @@ -2,21 +2,23 @@ using Microsoft.Extensions.Localization; using System.ComponentModel.DataAnnotations; using System.Reflection; -using System.Resources; namespace Infrastructure.Web { public class LocalizedValidationMetadataProvider : IValidationMetadataProvider { - private ResourceManager _resourceManager; - public LocalizedValidationMetadataProvider() + private IStringLocalizer _localizer; + + public LocalizedValidationMetadataProvider(IStringLocalizerFactory factory) { - _resourceManager = new ResourceManager("Resources", Assembly.GetEntryAssembly()); + this._localizer = factory.Create("Resources.Resource", Assembly.GetEntryAssembly().GetName().Name); } public void CreateValidationMetadata(ValidationMetadataProviderContext context) { - foreach (var res in Assembly.GetEntryAssembly().GetManifestResourceNames()) + var assembly = Assembly.GetExecutingAssembly(); + var resources = assembly.GetManifestResourceNames(); + foreach (var res in resources) { System.Diagnostics.Debug.WriteLine($"resource:{res} "); } @@ -26,7 +28,7 @@ namespace Infrastructure.Web if (validationAttribute != null && validationAttribute.ErrorMessage == null && validationAttribute.ErrorMessageResourceName == null) { var name = validationAttribute.GetType().Name; - validationAttribute.ErrorMessage = _resourceManager.GetString(name); + validationAttribute.ErrorMessage = _localizer.GetString(name); } } } diff --git a/labs/Teacher/TeacherExt/Models/EditTeacherModel.cs b/labs/Teacher/TeacherExt/Models/EditTeacherModel.cs index 14e765a3..4836259e 100644 --- a/labs/Teacher/TeacherExt/Models/EditTeacherModel.cs +++ b/labs/Teacher/TeacherExt/Models/EditTeacherModel.cs @@ -19,13 +19,13 @@ namespace TeacherExt.Models public int Id { get; set; } [ReadOnly(true)] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 3, Name = "申请修改状态")] public string RequestEditStatus { get; set; } = "未申请"; [SelectList] [ReadOnly(true)] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 4, Name = "审核状态")] public string CheckStatus { get; set; } = "未提交"; @@ -37,14 +37,14 @@ namespace TeacherExt.Models [ReadOnly(true)] [SkipSearch, SkipList] [Display(Order = 10, Name = "工作单位")] - [Required(ErrorMessage = "必填项")] + [Required] public string OrganName { get; set; } = "测试数据"; [ExcelHeader("姓名")] [ReadOnly(true)] [RegularExpression(@"^[\u4e00-\u9fa5\d]+$", ErrorMessage = "姓名格式错误")] [Display(Order = 20, Name = "教师姓名")] - [Required(ErrorMessage = "必填项")] + [Required] public string RealName { get; set; } [HiddenInput] @@ -55,33 +55,33 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 30, Name = "人员类别")] - [Required(ErrorMessage = "必填项")] + [Required] public int? UserType { get; set; } [ExcelHeader("性别")] [SkipSearch] [SelectList] [Display(Order = 40, Name = "性别")] - [Required(ErrorMessage = "必填项")] + [Required] public string Sex { get; set; } [SkipSearch, SkipList] [SelectList] [Display(Order = 30, Name = "婚姻状况")] - [Required(ErrorMessage = "必填项")] + [Required] public int MaritalStatus { get; set; } [SkipSearch] [SelectList] [Display(Order = 41, Name = "国籍")] - [Required(ErrorMessage = "必填项")] + [Required] public int? Nationality { get; set; } [ExcelHeader("出生年月")] [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 50, Name = "出生日期")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? Birthday { get; set; } @@ -97,14 +97,14 @@ namespace TeacherExt.Models [SkipSearch] [SelectList] [Display(Order = 70, Name = "民族")] - [Required(ErrorMessage = "必填项")] + [Required] public string Nation { get; set; } [ExcelHeader("籍贯")] [SkipSearch] [Description("以 省/自治区/直辖市 + 区/县 等形式填写")] [Display(Order = 80, Name = "籍贯")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string NativePlace { get; set; } @@ -112,7 +112,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [RegularExpression(@"(^$|^\d{7}$|^\d{11}$)", ErrorMessage = "电话号码格式错误")] [Display(Order = 90, Name = "联系电话")] - [Required(ErrorMessage = "必填项")] + [Required] public string PhoneNumber { get; set; } [SkipSearch, SkipList] @@ -125,14 +125,14 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [RegularExpression(@"^(\d{15}|\d{17}(X|\d))$", ErrorMessage = "身份证号格式错误")] [Display(Order = 100, Name = "身份证号")] - [Required(ErrorMessage = "必填项")] + [Required] public string IdNumber { get; set; } [ExcelHeader("参加工作\r\n时间")] [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 110, Name = "参加工作时间")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? WorkingTime { get; set; } @@ -152,7 +152,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 130, Name = "到现所在校时间")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? CurrentJobStart { get; set; } @@ -180,7 +180,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 150, Name = "政治面貌")] - [Required(ErrorMessage = "必填项")] + [Required] public int? Politics { get; set; } [ExcelHeader("入党(派)\r\n时间")] @@ -194,7 +194,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 170, Name = "最高职称")] - [Required(ErrorMessage = "必填项")] + [Required] public int? MaxTitle { get; set; } [SkipSearch, SkipList] @@ -215,7 +215,7 @@ namespace TeacherExt.Models [SelectList] [SkipSearch, SkipList] [Display(Order = 185, Name = "最高职称已聘")] - [Required(ErrorMessage = "必填项")] + [Required] public bool? IsJobAsMaxTitle { get; set; } [ExcelHeader("最高职称聘任时间,已聘\r\n(聘任时间)", "2,2")] @@ -224,7 +224,7 @@ namespace TeacherExt.Models [DataType(DataType.Date)] [Remote(nameof(JobAsMaxTitleDate), "Ajax", AdditionalFields = nameof(IsJobAsMaxTitle))] [Display(Order = 190, Name = "最高职称已聘聘任时间")] - [Required(ErrorMessage = "必填项")] + [Required] public DateTime? JobAsMaxTitleDate { get; set; } [SkipSearch, SkipList] @@ -236,7 +236,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [Description("如:乡村教师职评、暂未岗位变更、新考/调入等")] [Display(Order = 200, Name = "最高职称未聘原由")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string JobAsNotMaxTitleReason { get; set; } @@ -249,7 +249,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 210, Name = "现聘任职称")] - [Required(ErrorMessage = "必填项")] + [Required] public int? NotMaxTitle { get; set; } [SkipSearch, SkipList] @@ -261,7 +261,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 220, Name = "现聘任职称取得时间")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? NotMaxTitleStart { get; set; } @@ -274,7 +274,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 230, Name = "现聘任职称聘任时间")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? JobAsNotMaxTitleDate { get; set; } @@ -286,14 +286,14 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 240, Name = "岗位类别")] - [Required(ErrorMessage = "必填项")] + [Required] public int? PostType { get; set; } [ExcelHeader("现岗位等级")] [SkipSearch, SkipList] [SelectList] [Display(Order = 250, Name = "现岗位等级")] - [Required(ErrorMessage = "必填项")] + [Required] public string PostGrade { get; set; } [SkipSearch, SkipList] @@ -342,7 +342,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 280, Name = "享受学历待遇等级时间")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? EducationGradeDate { get; set; } @@ -354,7 +354,7 @@ namespace TeacherExt.Models [Description("填写毕业院校全称")] [SkipSearch, SkipList] [Display(Order = 290, Name = "全日制教育毕业院校")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string FullTimeSchool { get; set; } @@ -362,14 +362,14 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 300, Name = "全日制教育毕业院校分类")] - [Required(ErrorMessage = "必填项")] + [Required] public string FullTimeSchoolType { get; set; } [ExcelHeader("全日制教育,专业\r\n以毕业证书为准", "2,2")] [Description("严格按照毕业证书填写")] [SkipSearch, SkipList] [Display(Order = 310, Name = "全日制教育毕业证书专业")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string FullTimeSchoolMajor { get; set; } @@ -377,14 +377,14 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 320, Name = "全日制教育学历")] - [Required(ErrorMessage = "必填项")] + [Required] public int? FullTimeSchoolEducation { get; set; } [ExcelHeader("全日制教育,学历\r\n取得时间", "2,2")] [SkipSearch, SkipList] [Display(Order = 330, Name = "全日制教育学历取得时间")] [DataType(DataType.Date)] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? FullTimeSchoolEducationDate { get; set; } @@ -461,7 +461,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 420, Name = "主要任教学段")] - [Required(ErrorMessage = "必填项")] + [Required] public string MainTeachPeriod { get; set; } [SkipSearch, SkipList] @@ -473,7 +473,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList(true)] [Display(Order = 430, Name = "主要任教学科")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string MainTeachSubject { get; set; } @@ -485,7 +485,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 440, Name = "主要任教年级")] - [Required(ErrorMessage = "必填项")] + [Required] public string MainTeachGrade { get; set; } [SkipSearch, SkipList] @@ -516,14 +516,14 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 463, Name = "在编在岗")] public bool? HasPosition { get; set; } [HtmlData("HasPosition1")] [SkipSearch, SkipList] [SelectList] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 464, Name = "是否中层")] public bool? IsMiddleLevel { get; set; } @@ -533,7 +533,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList(true)] [Display(Order = 470, Name = "职务")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string Position { get; set; } @@ -545,7 +545,7 @@ namespace TeacherExt.Models [HtmlData("HasPosition11")] [SkipSearch, SkipList] [DataType(DataType.Date)] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 480, Name = "职务任命时间")] [Remote("ValidDate", "Ajax")] public DateTime? PositionStart { get; set; } @@ -559,7 +559,7 @@ namespace TeacherExt.Models [HtmlData("HasPosition12")] [SkipSearch, SkipList] [SelectList(true)] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 490, Name = "一线教师")] [MaxLength(50)] public string FrontTeacher { get; set; } @@ -569,7 +569,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList(true)] [Description("选择项中没有则手动填写")] - [Required(ErrorMessage = "必填项")] + [Required] [Display(Order = 500, Name = "不在岗原由")] [MaxLength(50)] public string NotOnPostReason { get; set; } @@ -583,7 +583,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [DataType(DataType.Date)] [Display(Order = 510, Name = "不在岗起始时间")] - [Required(ErrorMessage = "必填项")] + [Required] [Remote("ValidDate", "Ajax")] public DateTime? NotOnPostReasonDate { get; set; } @@ -595,7 +595,7 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList] [Display(Order = 520, Name = "教师资格证种类")] - [Required(ErrorMessage = "必填项")] + [Required] public string TeacherCardType { get; set; } [ExcelHeader("教师资格证\r\n任教学科\r\n(严格按照资格证书填写)")] @@ -615,14 +615,14 @@ namespace TeacherExt.Models [SkipSearch, SkipList] [SelectList(true)] [Display(Order = 550, Name = "现家庭地址-区县")] - [Required(ErrorMessage = "必填项")] + [Required] [MaxLength(50)] public string CurrentAddressArea { get; set; } [ExcelHeader("现住址详细地址\r\n(街道 - 小区)")] [SkipSearch, SkipList] [Display(Order = 560, Name = "现家庭详细地址")] - [Required(ErrorMessage = "必填项")] + [Required] [DataType(DataType.MultilineText)] [MaxLength(100)] public string AddressDetails { get; set; } diff --git a/labs/Teacher/TeacherExt/Models/LoginModel.cs b/labs/Teacher/TeacherExt/Models/LoginModel.cs index 70a739ff..5d6d1bd3 100644 --- a/labs/Teacher/TeacherExt/Models/LoginModel.cs +++ b/labs/Teacher/TeacherExt/Models/LoginModel.cs @@ -6,7 +6,7 @@ namespace TeacherExt.Models { public class LoginModel { - [Display(Name = "person_id")] + [Display(Name = "用户名")] [Required] public string UserName { get; set; } diff --git a/labs/Teacher/TeacherExt/Startup.cs b/labs/Teacher/TeacherExt/Startup.cs index 98817496..502c3a9d 100644 --- a/labs/Teacher/TeacherExt/Startup.cs +++ b/labs/Teacher/TeacherExt/Startup.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Localization; +using Microsoft.Extensions.Localization; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -25,6 +26,7 @@ using System.Text.Encodings.Web; using System.Text.Unicode; using System.Threading.Tasks; using TeacherExt.Data; +using Microsoft.AspNetCore.Mvc.DataAnnotations; namespace TeacherExt { @@ -67,6 +69,7 @@ namespace TeacherExt services.AddTransient(); services.AddTransient(); services.AddLocalization(options => options.ResourcesPath = null); + //services.AddSingleton(); services.AddSingleton(); services.Configure( options => @@ -82,19 +85,21 @@ namespace TeacherExt options.SupportedUICultures = supportedCultures; options.RequestCultureProviders.Insert(0, new QueryStringRequestCultureProvider()); }); - services.AddMvc() + services.AddMvc(o => o.ModelMetadataDetailsProviders.Add( + new LocalizedValidationMetadataProvider(services.BuildServiceProvider().GetRequiredService())) + ) .AddNewtonsoftJson() - .AddControllersAsServices() - .AddMvcLocalization() - .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) - .AddDataAnnotationsLocalization(options => - { - options.DataAnnotationLocalizerProvider = (type, factory) => - { - var localizer = factory.Create("Resource", Assembly.GetEntryAssembly().GetName().Name); - return localizer; - }; - }); + .AddControllersAsServices(); + //.AddMvcLocalization() + //.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) + //.AddDataAnnotationsLocalization(options => + //{ + // options.DataAnnotationLocalizerProvider = (type, factory) => + // { + // var localizer = factory.Create("Resources.Resource", Assembly.GetEntryAssembly().GetName().Name); + // return localizer; + // }; + //}); services.AddControllers() .ConfigureApiBehaviorOptions(options =>