我在一个解决方案中有2个项目。其中一个名为UICORE,另一个名为DomainCore。 UICore是一个ASPNETCORE项目,它有我的控制器和视图。 DomainCore是一个包含所有实体类的类库。我想使用本地化的DataAnnotations。我研究过“https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization”,但我无法让它为我工作。
如果Domain和View模型的DataAnnotations遇到您的问题(或其中的一部分),我建议使用此方法。
如果没有,请不要downvote。它可能对Data Annotations标签很有用。
要编写一次DataAnnotations,请使用抽象类。在New实体的这个例子中,我命名了抽象类NewMetaData。
DomainCore项目:
namespace myProject.DomainCore
{
public class New : NewMetaData
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
}
public abstract class NewMetaData
{
[Required(ErrorMessage = "New Title is required")]
[StringLength(maximumLength:150, ErrorMessage = "New Title length must not exceed 150 characters")]
[Display(Name = "Title on New")]
private string Title { get; set; } //pay attention to privates
[Required(ErrorMessage = "New Content is required")]
[Display(Name = "Content of New")]
private string Content { get; set; }
[Required]
[Display(Name = "Publish Date")]
private DateTime Date { get; set; }
}
}
并且UICore项目中的viewmodel类也必须继承NewMetaData类:
namespace myProject.UICore.Models.News
{
public class NewCreateModel: NewMetaData
{
public string Title { get; set; }
[AllowHtml]
public string Content { get; set; }
}
public class NewDetailsModel :NewMetaData
{
[HiddenInput(DisplayValue = false)]
public Guid Id { get; set; }
public string Url { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
}
正如您所看到的,您可以向UICore中的Allow Html,Hidden Input和...等属性添加额外的数据注释,并且仍然保持基本Annotations不变。
这是一次最简单的跨项目方法,用于对模型进行一次注释并多次使用它们。
希望能帮助到你。
也许这会有所帮助:https://damienbod.com/2015/10/24/using-dataannotations-and-localization-in-asp-net-5-mvc-6/
您需要将数据注释本地化添加到共享资源,并将其添加到每个控制器,查看它与本地化响应一起使用的位置。
您必须在启动文件中配置本地化,并添加DataAnnotations本地化选项;
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddViewLocalization(o=>o.ResourcesPath = "ResourcesFolder")
.AddDataAnnotationsLocalization(o=> {
var type = typeof(MyResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
var factory = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
var localizer = factory.Create("MyResource", assemblyName.Name);
o.DataAnnotationLocalizerProvider = (t, f) => localizer;
})
这将本地化数据属性,如:
[Required(ErrorMessage= "...")]
[StringLength(ErrorMessage= "...")]
[Range(ErrorMessage= "...")]
等等..
但您仍然需要配置ModelBinding错误消息(例如:检查数字,空值,等等)
services.AddMvc()
.AddMvcOptions(o =>
{
var type = typeof(MyResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
var factory = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
var localizer = factory.Create("MyResource", assemblyName.Name);
o.ModelBindingMessageProvider
.SetAttemptedValueIsInvalidAccessor((x, y) => localizer["'{0}' is not a valid value for '{1}'", x, y]);
o.ModelBindingMessageProvider
.SetValueMustBeANumberAccessor((x) => localizer["'{0}' must be a number.", x]);
});
如果您已经实现了身份系统,则必须通过重写IdentityErrorDescriber方法来本地化身份错误消息(重复的电子邮件,密码策略等);
public class LocalizedIdentityErrorDescriber : IdentityErrorDescriber
{
public override IdentityError DuplicateEmail(string email)
{
return new IdentityError
{
Code = nameof(DuplicateEmail),
Description = string.Format(LocalizedIdentityErrorMessages.DuplicateEmail, email)
};
}
public override IdentityError DuplicateUserName(string userName)
{
return new IdentityError
{
Code = nameof(DuplicateUserName),
Description = string.Format(LocalizedIdentityErrorMessages.DuplicateUserName, userName)
};
}
public override IdentityError InvalidEmail(string email)
{
return new IdentityError
{
Code = nameof(InvalidEmail),
Description = string.Format(LocalizedIdentityErrorMessages.InvalidEmail, email)
};
}
public override IdentityError DuplicateRoleName(string role)
{
return new IdentityError
{
Code = nameof(DuplicateRoleName),
Description = string.Format(LocalizedIdentityErrorMessages.DuplicateRoleName, role)
};
}
public override IdentityError InvalidRoleName(string role)
{
return new IdentityError
{
Code = nameof(InvalidRoleName),
Description = string.Format(LocalizedIdentityErrorMessages.InvalidRoleName, role)
};
}
public override IdentityError InvalidToken()
{
return new IdentityError
{
Code = nameof(InvalidToken),
Description = LocalizedIdentityErrorMessages.InvalidToken
};
}
public override IdentityError InvalidUserName(string userName)
{
return new IdentityError
{
Code = nameof(InvalidUserName),
Description = string.Format(LocalizedIdentityErrorMessages.InvalidUserName, userName)
};
}
public override IdentityError LoginAlreadyAssociated()
{
return new IdentityError
{
Code = nameof(LoginAlreadyAssociated),
Description = LocalizedIdentityErrorMessages.LoginAlreadyAssociated
};
}
public override IdentityError PasswordMismatch()
{
return new IdentityError
{
Code = nameof(PasswordMismatch),
Description = LocalizedIdentityErrorMessages.PasswordMismatch
};
}
public override IdentityError PasswordRequiresDigit()
{
return new IdentityError
{
Code = nameof(PasswordRequiresDigit),
Description = LocalizedIdentityErrorMessages.PasswordRequiresDigit
};
}
public override IdentityError PasswordRequiresLower()
{
return new IdentityError
{
Code = nameof(PasswordRequiresLower),
Description = LocalizedIdentityErrorMessages.PasswordRequiresLower
};
}
public override IdentityError PasswordRequiresNonAlphanumeric()
{
return new IdentityError
{
Code = nameof(PasswordRequiresNonAlphanumeric),
Description = LocalizedIdentityErrorMessages.PasswordRequiresNonAlphanumeric
};
}
public override IdentityError PasswordRequiresUniqueChars(int uniqueChars)
{
return new IdentityError
{
Code = nameof(PasswordRequiresUniqueChars),
Description = string.Format(LocalizedIdentityErrorMessages.PasswordRequiresUniqueChars, uniqueChars)
};
}
public override IdentityError PasswordRequiresUpper()
{
return new IdentityError
{
Code = nameof(PasswordRequiresUpper),
Description = LocalizedIdentityErrorMessages.PasswordRequiresUpper
};
}
public override IdentityError PasswordTooShort(int length)
{
return new IdentityError
{
Code = nameof(PasswordTooShort),
Description = string.Format(LocalizedIdentityErrorMessages.PasswordTooShort, length)
};
}
public override IdentityError UserAlreadyHasPassword()
{
return new IdentityError
{
Code = nameof(UserAlreadyHasPassword),
Description = LocalizedIdentityErrorMessages.UserAlreadyHasPassword
};
}
public override IdentityError UserAlreadyInRole(string role)
{
return new IdentityError
{
Code = nameof(UserAlreadyInRole),
Description = string.Format(LocalizedIdentityErrorMessages.UserAlreadyInRole, role)
};
}
public override IdentityError UserNotInRole(string role)
{
return new IdentityError
{
Code = nameof(UserNotInRole),
Description = string.Format(LocalizedIdentityErrorMessages.UserNotInRole, role)
};
}
public override IdentityError UserLockoutNotEnabled()
{
return new IdentityError
{
Code = nameof(UserLockoutNotEnabled),
Description = LocalizedIdentityErrorMessages.UserLockoutNotEnabled
};
}
public override IdentityError RecoveryCodeRedemptionFailed()
{
return new IdentityError
{
Code = nameof(RecoveryCodeRedemptionFailed),
Description = LocalizedIdentityErrorMessages.RecoveryCodeRedemptionFailed
};
}
public override IdentityError ConcurrencyFailure()
{
return new IdentityError
{
Code = nameof(ConcurrencyFailure),
Description = LocalizedIdentityErrorMessages.ConcurrencyFailure
};
}
public override IdentityError DefaultError()
{
return new IdentityError
{
Code = nameof(DefaultError),
Description = LocalizedIdentityErrorMessages.DefaultIdentityError
};
}
}
在此示例中,所有本地化标识错误消息都在名为LocalizedIdentityErrorMessages且具有公共访问修饰符的资源文件中提供。
你可以查看这些关于本地化的文章,它包含GitHub上的现场演示和示例项目。
开发多元文化网络应用程序:http://www.ziyad.info/en/articles/10-Developing_Multicultural_Web_Application
本地化数据注释:http://www.ziyad.info/en/articles/16-Localizing_DataAnnotations
本地化身份错误消息:http://www.ziyad.info/en/articles/20-Localizing_Identity_Error_Messages
本地化ModelBinding错误消息:http://www.ziyad.info/en/articles/18-Localizing_ModelBinding_Error_Messages
客户端验证:http://www.ziyad.info/en/articles/19-Client_Side_Validation