Model view controller 比较日期数据批注验证asp.net mvc

Model view controller 比较日期数据批注验证asp.net mvc,model-view-controller,validation,compare,date,data-annotations,Model View Controller,Validation,Compare,Date,Data Annotations,假设我有一个开始日期和结束日期,我需要检查结束日期是否与开始日期相差不超过3个月 public class DateCompare : ValidationAttribute { public String StartDate { get; set; } public String EndDate { get; set; } //Constructor to take in the property names that are supposed to be che

假设我有一个开始日期和结束日期,我需要检查结束日期是否与开始日期相差不超过3个月

public class DateCompare : ValidationAttribute 
 {
    public String StartDate { get; set; }
    public String EndDate { get; set; }

    //Constructor to take in the property names that are supposed to be checked
    public DateCompare(String startDate, String endDate)
    {
        StartDate = startDate;
        EndDate = endDate;
    }

    public override bool IsValid(object value)
    {
        var str = value.ToString();
        if (string.IsNullOrEmpty(str))
            return true;

        DateTime theEndDate = DateTime.ParseExact(EndDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
        DateTime theStartDate = DateTime.ParseExact(StartDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture).AddMonths(3);
        return (DateTime.Compare(theStartDate, theEndDate) > 0);
    }
}
我想在我的验证中实现这一点

[DateCompare(“StartDate”、“EndDate”、ErrorMessage=“交易只能持续3个月!”)


我知道我这里有个错误。。。但是如何在asp.net mvc中进行此类业务规则验证我只知道如何在类级别进行验证,而没有在属性级别进行验证。如果您创建一个MVC应用程序,帐户模型将显示如下所示的方法

类别:

  [PropertiesMustMatch("Password",
            "ConfirmPassword", ErrorMessage =
            "Password and confirmation password
            do not match.")]
                public class RegisterModel
                {

                    [Required(ErrorMessage = "Required")]
                    [DataType(DataType.EmailAddress)]
                    [DisplayName("Your Email")]
                    public string Email { get; set; }              

                    [Required(ErrorMessage = "Required")]
                    [ValidatePasswordLength]
                    [DataType(DataType.Password)]
                    [DisplayName("Password")]
                    public string Password { get; set; }

                    [Required(ErrorMessage = "Required")]
                    [DataType(DataType.Password)]
                    [DisplayName("Re-enter password")]
                    public string ConfirmPassword { get; set; }                
                }
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public sealed class PropertiesMustMatchAttribute : ValidationAttribute
    {
        private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";

        private readonly object _typeId = new object();

        public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
            : base(_defaultErrorMessage)
        {
            OriginalProperty = originalProperty;
            ConfirmProperty = confirmProperty;
        }

        public string ConfirmProperty
        {
            get;
            private set;
        }

        public string OriginalProperty
        {
            get;
            private set;
        }

        public override object TypeId
        {
            get
            {
                return _typeId;
            }
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
                OriginalProperty, ConfirmProperty);
        }

        public override bool IsValid(object value)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
            object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
            object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
            return Object.Equals(originalValue, confirmValue);
        }
}
验证方法:

  [PropertiesMustMatch("Password",
            "ConfirmPassword", ErrorMessage =
            "Password and confirmation password
            do not match.")]
                public class RegisterModel
                {

                    [Required(ErrorMessage = "Required")]
                    [DataType(DataType.EmailAddress)]
                    [DisplayName("Your Email")]
                    public string Email { get; set; }              

                    [Required(ErrorMessage = "Required")]
                    [ValidatePasswordLength]
                    [DataType(DataType.Password)]
                    [DisplayName("Password")]
                    public string Password { get; set; }

                    [Required(ErrorMessage = "Required")]
                    [DataType(DataType.Password)]
                    [DisplayName("Re-enter password")]
                    public string ConfirmPassword { get; set; }                
                }
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public sealed class PropertiesMustMatchAttribute : ValidationAttribute
    {
        private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";

        private readonly object _typeId = new object();

        public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
            : base(_defaultErrorMessage)
        {
            OriginalProperty = originalProperty;
            ConfirmProperty = confirmProperty;
        }

        public string ConfirmProperty
        {
            get;
            private set;
        }

        public string OriginalProperty
        {
            get;
            private set;
        }

        public override object TypeId
        {
            get
            {
                return _typeId;
            }
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
                OriginalProperty, ConfirmProperty);
        }

        public override bool IsValid(object value)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
            object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
            object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
            return Object.Equals(originalValue, confirmValue);
        }
}
属性

public class CompareValidatorAttribute : ValidationAttribute, IInstanceValidationAttribute
{
    public CompareValidatorAttribute(string prefix, string propertyName) {
        Check.CheckNullArgument("propertyName", propertyName);

        this.propertyName = propertyName;
        this.prefix = prefix;
    }

    string propertyName, prefix;

    public string PropertyName
    {
        get { return propertyName; }
    }

    public string Prefix
    {
        get { return prefix; }
    }

    #region IInstanceValidationAttribute Members

    public bool IsValid(object instance, object value)
    {
        var property = instance.GetType().GetProperty(propertyName);

        var targetValue = property.GetValue(instance, null);
        if ((targetValue == null && value == null) || (targetValue != null && targetValue.Equals(value)))
            return true;

        return false;
    }

    #endregion

    public override bool IsValid(object value)
    {
        throw new NotImplementedException();
    }
}
接口

public interface IInstanceValidationAttribute
{
    bool IsValid(object instance, object value);
}
验证器

public class CompareValidator : DataAnnotationsModelValidator<CompareValidatorAttribute>
{
    public CompareValidator(ModelMetadata metadata, ControllerContext context, CompareValidatorAttribute attribute)
        : base(metadata, context, attribute)
    {
    }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        if (!(Attribute as IInstanceValidationAttribute).IsValid(container, Metadata.Model))
            yield return (new ModelValidationResult
            {
                MemberName = Metadata.PropertyName,
                Message = Attribute.ErrorMessage
            });
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        var rule = new ModelClientValidationRule() { ErrorMessage = Attribute.ErrorMessage, ValidationType = "equalTo" };
        rule.ValidationParameters.Add("equalTo", "#" + (!string.IsNullOrEmpty(Attribute.Prefix) ? Attribute.Prefix + "_" : string.Empty)+ Attribute.PropertyName);

        return new[] { rule };
    }
}

谢谢你的信息。当我想将验证消息绑定到一个属性时,我一直在挠头。如果你换线

[AttributeUsage(AttributeTargets.Class)]

可以将比较移动到特定属性上方。谢谢你的信息!由于我的客户机仍在3.5SP1上运行,因此帮助很大。愁容

  • 日期
  • 实体:

    [MetadataType(typeof(MyEntity_Validation))]
    public partial class MyEntity
    {
    }
    public class MyEntity_Validation
    {
        [Required(ErrorMessage="'Date from' is required")]
        public DateTime DateFrom { get; set; }
    
        [CompareDatesValidatorAttribute("DateFrom")]  
        public DateTime DateTo { get; set; }
    }
    
       public string Password { get; set; }
    
        [Compare("Password", ErrorMessage = "ConfirmPassword must match Password")]
        public string ConfirmPassword { get; set; }
    
    属性:

     public sealed class CompareDatesValidatorAttribute : ValidationAttribute
    {
        private string _dateToCompare;  
        private const string _errorMessage = "'{0}' must be greater or equal'{1}'";  
    
        public CompareDatesValidatorAttribute(string dateToCompare)
            : base(_errorMessage)
        {
            _dateToCompare = dateToCompare;
        }
    
        public override string FormatErrorMessage(string name)
        {
            return string.Format(_errorMessage, name, _dateToCompare);
        } 
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var dateToCompare = validationContext.ObjectType.GetProperty(_dateToCompare);
            var dateToCompareValue = dateToCompare.GetValue(validationContext.ObjectInstance, null);
            if (dateToCompareValue != null && value != null && (DateTime)value < (DateTime)dateToCompareValue) 
            {
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
            }
            return null;
        }
    }
    

    我希望这能有所帮助,这是一个迟来的答案,但我想与其他人分享。我是这样做的,以便使用不引人注目的客户端验证对所有内容进行验证:

  • 创建属性类:

    public class DateCompareValidationAttribute : ValidationAttribute, IClientValidatable
    {
    
      public enum CompareType
      {
          GreatherThen,
          GreatherThenOrEqualTo,
          EqualTo,
          LessThenOrEqualTo,
          LessThen
      }
    
    
    
    
      private CompareType _compareType;
      private DateTime _fromDate;
      private DateTime _toDate;
    
      private string _propertyNameToCompare;
    
      public DateCompareValidationAttribute(CompareType compareType, string message, string compareWith = "")
    {
        _compareType = compareType;
        _propertyNameToCompare = compareWith;
        ErrorMessage = message;
    }
    
    
    #region IClientValidatable Members
    /// <summary>
    /// Generates client validation rules
    /// </summary>
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ValidateAndGetCompareToProperty(metadata.ContainerType);
        var rule = new ModelClientValidationRule();
    
        rule.ErrorMessage = ErrorMessage;
        rule.ValidationParameters.Add("comparetodate", _propertyNameToCompare);
        rule.ValidationParameters.Add("comparetype", _compareType);
        rule.ValidationType = "compare";
    
        yield return rule;
    }
    
    #endregion
    
    
     protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
         // Have to override IsValid method. If you have any logic for server site validation, put it here. 
        return ValidationResult.Success;
    
    }
    
    /// <summary>
    /// verifies that the compare-to property exists and of the right types and returnes this property
    /// </summary>
    /// <param name="containerType">Type of the container object</param>
    /// <returns></returns>
    private PropertyInfo ValidateAndGetCompareToProperty(Type containerType)
    {
        var compareToProperty = containerType.GetProperty(_propertyNameToCompare);
        if (compareToProperty == null)
        {
            string msg = string.Format("Invalid design time usage of {0}. Property {1} is not found in the {2}", this.GetType().FullName, _propertyNameToCompare, containerType.FullName);
            throw new ArgumentException(msg);
        }
        if (compareToProperty.PropertyType != typeof(DateTime) && compareToProperty.PropertyType != typeof(DateTime?))
        {
            string msg = string.Format("Invalid design time usage of {0}. The type of property {1} of the {2} is not DateType", this.GetType().FullName, _propertyNameToCompare, containerType.FullName);
            throw new ArgumentException(msg);
        }
    
        return compareToProperty;
    }
    }
    

    这只考虑客户端不引人注目的验证。如果需要服务器端,则必须在isValid方法的重写中包含一些逻辑。此外,您还可以使用反射来使用显示属性等生成错误消息,并将消息参数设置为可选

    你创建了那个类吗?还是你在什么地方找到的?当密码不匹配时,不会显示错误。我一定错过了什么。不必担心,MVCIt是基本MVC应用程序的一部分。它将错误添加到_表单中,而不是添加到特定实体中。对此有答案吗?奥利弗,什么对你有用?很好很短的例子。不需要jQuery的$.validator。
    $.validator.addMethod("compare", function (value, element, parameters) {
        // value is the actuall value entered 
        // element is the field itself, that contain the the value (in case the value is not enough)
    
        var errMsg = "";
        // validate parameters to make sure everyting the usage is right
        if (parameters.comparetodate == undefined) {
            errMsg = "Compare validation cannot be executed: comparetodate parameter not found";
            alert(errMsg);
            return false;
        }
        if (parameters.comparetype == undefined) {
            errMsg = "Compare validation cannot be executed: comparetype parameter not found";
            alert(errMsg);
            return false;
        }
    
    
        var compareToDateElement = $('#' + parameters.comparetodate).get();
        if (compareToDateElement.length == 0) {
            errMsg = "Compare validation cannot be executed: Element to compare " + parameters.comparetodate + " not found";
            alert(errMsg);
            return false;
        }
        if (compareToDateElement.length > 1) {
            errMsg = "Compare validation cannot be executed: more then one Element to compare with id " + parameters.comparetodate + " found";
            alert(errMsg);
            return false;
        }
        //debugger;
    
        if (value && !isNaN(Date.parse(value))) {
            //validate only the value contains a valid date. For invalid dates and blanks non-custom validation should be used    
            //get date to compare
            var compareToDateValue = $('#' + parameters.comparetodate).val();
            if (compareToDateValue && !isNaN(Date.parse(compareToDateValue))) {
                //if date to compare is not a valid date, don't validate this
                switch (parameters.comparetype) {
                    case 'GreatherThen':
                        return new Date(value) > new Date(compareToDateValue);
                    case 'GreatherThenOrEqualTo':
                        return new Date(value) >= new Date(compareToDateValue);
                    case 'EqualTo':
                        return new Date(value) == new Date(compareToDateValue);
                    case 'LessThenOrEqualTo':
                        return new Date(value) <= new Date(compareToDateValue);
                    case 'LessThen':
                        return new Date(value) < new Date(compareToDateValue);
                    default:
                        {
                            errMsg = "Compare validation cannot be executed: '" + parameters.comparetype + "' is invalid for comparetype parameter";
                            alert(errMsg);
                            return false;
                        }
                }
                return true;
            }
            else
                return true;
    
        }
        else
            return true;
    });