Pau*_*les 9 validation asp.net-mvc data-annotations asp.net-mvc-2
我通过继承ValidationAttribute创建了一个自定义验证属性.该属性在类级别应用于我的viewmodel,因为它需要验证多个属性.
我压倒一切
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
Run Code Online (Sandbox Code Playgroud)
并返回:
new ValidationResult("Always Fail", new List<string> { "DateOfBirth" });
Run Code Online (Sandbox Code Playgroud)
在所有情况下,DateOfBirth是我的视图模型上的属性之一.
当我运行我的应用程序时,我可以看到它被击中.ModelState.IsValid正确设置为false但是当我检查ModelState内容时,我看到Property DateOfBirth不包含任何错误.相反,我有一个值为null的空字符串Key和一个包含我在验证属性中指定的字符串的异常.
这导致在使用ValidationMessageFor时,我的UI中不显示任何错误消息.如果我使用ValidationSummary,那么我可以看到错误.这是因为它与属性无关.
它看起来好像忽略了我在验证结果中指定了membername的事实.
为什么这样,我该如何解决?
要求的示例代码:
[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; }
}
Run Code Online (Sandbox Code Playgroud)
小智 13
大家好.
仍在寻找解决方案?
我今天解决了同样的问题.您必须创建自定义验证属性,该属性将验证2个日期(下面的示例).然后你需要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);
}
}
Run Code Online (Sandbox Code Playgroud)
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
};
}
}
}
Run Code Online (Sandbox Code Playgroud)
Global.asax中:
protected void Application_Start()
{
// ...
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(DateCompareAttribute), typeof(DateCompareAttributeAdapter));
}
Run Code Online (Sandbox Code Playgroud)
CustomViewModel.cs:
[DateCompare("StartDateTime", "EndDateTime", DateCompareAttribute.Operations.LesserOrEquals)]
public class CustomViewModel
{
// Properties...
public DateTime? StartDateTime
{
get;
set;
}
public DateTime? EndDateTime
{
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道有什么简单的方法可以解决此行为。这就是我讨厌数据注释的原因之一。使用FluentValidation做同样的事情将是小菜一碟:
public class ExampleViewModelValidator: AbstractValidator<ExampleViewModel>
{
public ExampleViewModelValidator()
{
RuleFor(x => x.EndDate)
.GreaterThan(x => x.StartDate)
.WithMessage("end date must be after start date");
}
}
Run Code Online (Sandbox Code Playgroud)
FluentValidation对 ASP.NET MVC 有很好的支持和集成。
| 归档时间: |
|
| 查看次数: |
3478 次 |
| 最近记录: |