我在ASP.NET MVC3中创建了一个这样的继承属性:
public sealed class RequiredFromResourceAttribute : RequiredAttribute
{
public RequiredFromResourceAttribute(string errorResourceName, string errorResourceTypeName)
{
this.ErrorMessageResourceName = errorResourceName;
this.ErrorMessageResourceType = Type.GetType(errorResourceTypeName);
}
}
并像这样使用它:
[RequiredFromResource("Title", "Resources.Resource, MyProject.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")]
public string Title { get; set; }
它不起作用,MVC忽略了它。然后我创建一个更简单的类,它继承自RequiredAttribute,如下所示:
public class MyRequiredAttribute : RequiredAttribute
{
}
我就像我说的那样使用它。但它没有再起作用。
尽管如此,所有这些方式都完美地适用于“DisplayNameAtrribute”。
有什么问题?
答案 0 :(得分:3)
这只是客户端验证,不适用于继承的属性。原因是当将服务器端属性映射到客户端验证行为时,MVC使用严格类型相等。
要解决此问题,您需要使用自定义属性来实现IClientValidatable
:
public class MyRequiredAttribute : IClientValidatable {
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
yield return new ModelClientValidationRequiredRule();
}
}
答案 1 :(得分:3)
您可以通过在Global.asax中添加以下代码来解决此问题:(找到答案here)
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredLocalizableAttribute), typeof(RequiredAttributeAdapter));
或者,使用marcind的解决方案,我发现ModelClientValidationRequiredRule
的构造函数需要一条错误消息。这是一个更新版本,其中包含该字段的显示名称:
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
string msg = FormatErrorMessage(metadata.GetDisplayName());
yield return new ModelClientValidationRequiredRule(msg);
}
答案 2 :(得分:0)
在上面的基础上,使用默认资源字符串Resource.ValueRequired定义了LocalizedRequiredAttribute的完整属性,该字符串在我的资源中定义为 “ {0}字段为必填。”
public class LocalizedRequiredAttribute : RequiredAttribute, IClientValidatable
{
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var msg = new ResourceManager(ErrorMessageResourceType).GetString(ErrorMessageResourceName);
yield return new ModelClientValidationRequiredRule(string.Format(msg, metadata.DisplayName));
}
public LocalizedRequiredAttribute(string errorResourceName = null, string errorResourceTypeName = null)
{
this.ErrorMessageResourceName = string.IsNullOrEmpty(errorResourceName) ? nameof(Resource.ValueRequired) : errorResourceName;
this.ErrorMessageResourceType = string.IsNullOrEmpty(errorResourceTypeName) ? typeof(Resource) : Type.GetType(errorResourceTypeName);
}
}