无法从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

下一篇: Require One From Group