无法从MVC2中的自定义验证属性设置成员名称
我通过继承ValidationAttribute创建了一个自定义验证属性。 该属性应用于我的视图模型在类级别,因为它需要验证多个属性。
我是压倒性的
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
并返回:
new ValidationResult("Always Fail", new List<string> { "DateOfBirth" });
在所有情况下,DateOfBirth是我的视图模型中的一个属性。
当我运行我的应用程序时,我可以看到这受到打击。 ModelState.IsValid设置为false,但当我检查ModelState内容时,我发现Property DateOfBirth不包含任何错误。 相反,我有一个空字符串键值为null,并且包含我在我的验证属性中指定的字符串的异常。
这会导致在使用ValidationMessageFor时,我的UI中不会显示错误消息。 如果我使用ValidationSummary,那么我可以看到错误。 这是因为它与一个属性没有关联。
它看起来好像忽略了我在验证结果中指定了成员名的事实。
为什么是这个,我该如何解决它?
示例代码请求:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ExampleValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// note that I will be doing complex validation of multiple properties when complete so this is why it is a class level attribute
return new ValidationResult("Always Fail", new List<string> { "DateOfBirth" });
}
}
[ExampleValidation]
public class ExampleViewModel
{
public string DateOfBirth { get; set; }
}
我不知道一个简单的方法来解决这个问题。 这是我讨厌数据注释的原因之一。 用FluentValidation做同样的事情将是蛋糕的平安:
public class ExampleViewModelValidator: AbstractValidator<ExampleViewModel>
{
public ExampleViewModelValidator()
{
RuleFor(x => x.EndDate)
.GreaterThan(x => x.StartDate)
.WithMessage("end date must be after start date");
}
}
FluentValidation对ASP.NET MVC有很好的支持和集成。
大家好。
仍在寻找解决方案?
我今天解决了同样的问题。 你必须创建自定义验证属性来验证两个日期(下面的例子)。 然后你需要Adapter(验证器),它将用你的自定义属性验证模型。 最后一件事是绑定适配器和属性。 也许一些例子会比我更好地解释它:)
开始了:
DateCompareAttribute.cs:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class DateCompareAttribute : ValidationAttribute
{
public enum Operations
{
Equals,
LesserThan,
GreaterThan,
LesserOrEquals,
GreaterOrEquals,
NotEquals
};
private string _From;
private string _To;
private PropertyInfo _FromPropertyInfo;
private PropertyInfo _ToPropertyInfo;
private Operations _Operation;
public string MemberName
{
get
{
return _From;
}
}
public DateCompareAttribute(string from, string to, Operations operation)
{
_From = from;
_To = to;
_Operation = operation;
//gets the error message for the operation from resource file
ErrorMessageResourceName = "DateCompare" + operation.ToString();
ErrorMessageResourceType = typeof(ValidationStrings);
}
public override bool IsValid(object value)
{
Type type = value.GetType();
_FromPropertyInfo = type.GetProperty(_From);
_ToPropertyInfo = type.GetProperty(_To);
//gets the values of 2 dates from model (using reflection)
DateTime? from = (DateTime?)_FromPropertyInfo.GetValue(value, null);
DateTime? to = (DateTime?)_ToPropertyInfo.GetValue(value, null);
//compare dates
if ((from != null) && (to != null))
{
int result = from.Value.CompareTo(to.Value);
switch (_Operation)
{
case Operations.LesserThan:
return result == -1;
case Operations.LesserOrEquals:
return result <= 0;
case Operations.Equals:
return result == 0;
case Operations.NotEquals:
return result != 0;
case Operations.GreaterOrEquals:
return result >= 0;
case Operations.GreaterThan:
return result == 1;
}
}
return true;
}
public override string FormatErrorMessage(string name)
{
DisplayNameAttribute aFrom = (DisplayNameAttribute)_FromPropertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
DisplayNameAttribute aTo = (DisplayNameAttribute)_ToPropertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
return string.Format(ErrorMessageString,
!string.IsNullOrWhiteSpace(aFrom.DisplayName) ? aFrom.DisplayName : _From,
!string.IsNullOrWhiteSpace(aTo.DisplayName) ? aTo.DisplayName : _To);
}
}
DateCompareAttributeAdapter.cs:
public class DateCompareAttributeAdapter : DataAnnotationsModelValidator<DateCompareAttribute>
{
public DateCompareAttributeAdapter(ModelMetadata metadata, ControllerContext context, DateCompareAttribute attribute)
: base(metadata, context, attribute) {
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (!Attribute.IsValid(Metadata.Model))
{
yield return new ModelValidationResult
{
Message = ErrorMessage,
MemberName = Attribute.MemberName
};
}
}
}
Global.asax中:
protected void Application_Start()
{
// ...
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(DateCompareAttribute), typeof(DateCompareAttributeAdapter));
}
CustomViewModel.cs:
[DateCompare("StartDateTime", "EndDateTime", DateCompareAttribute.Operations.LesserOrEquals)]
public class CustomViewModel
{
// Properties...
public DateTime? StartDateTime
{
get;
set;
}
public DateTime? EndDateTime
{
get;
set;
}
}
当返回验证结果时,使用两个参数构造函数。 将context.MemberName作为唯一值传递给一个数组。 希望这可以帮助
<AttributeUsage(AttributeTargets.Property Or AttributeTargets.Field, AllowMultiple:=False)>
Public Class NonNegativeAttribute
Inherits ValidationAttribute
Public Sub New()
End Sub
Protected Overrides Function IsValid(num As Object, context As ValidationContext) As ValidationResult
Dim t = num.GetType()
If (t.IsValueType AndAlso Not t.IsAssignableFrom(GetType(String))) Then
If ((num >= 0)) Then
Return ValidationResult.Success
End If
Return New ValidationResult(context.MemberName & " must be a positive number", New String() {context.MemberName})
End If
Throw New ValidationException(t.FullName + " is not a valid type. Must be a number")
End Function
End Class
链接地址: http://www.djcxy.com/p/56645.html
上一篇: Unable to set membernames from custom validation attribute in MVC2