比较日期 DataAnnotations Validation asp.net mvc [英] Compare Dates DataAnnotations Validation asp.net mvc

查看:24
本文介绍了比较日期 DataAnnotations Validation asp.net mvc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 StartDate 和一个 EndDate,我不想检查 EndDate 是否与开始日期相差不超过 3 个月

 公共类 DateCompare : ValidationAttribute{公共字符串开始日期 { 获取;放;}公共字符串结束日期 { 获取;放;}//构造函数接收应该检查的属性名称公共日期比较(字符串开始日期,字符串结束日期){开始日期 = 开始日期;结束日期 = 结束日期;}公共覆盖 bool IsValid(对象值){var str = value.ToString();如果 (string.IsNullOrEmpty(str))返回真;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);返回 (DateTime.Compare(theStartDate, theEndDate) > 0);}}

我想在我的验证中实现这一点

<块引用>

[DateCompare("StartDate", "EndDate", ErrorMessage = "交易只能持续 3 个月!")]

我知道我在这里遇到错误...但是我怎样才能在 asp.net mvc 中进行这种业务规则验证

解决方案

这是一个迟到的答案,但我想与其他人分享.以下是我的做法,以便使用不显眼的客户端验证来验证所有内容:

  1. 创建属性类:

    公共类 DateCompareValidationAttribute : ValidationAttribute, IClientValidatable{公共枚举比较类型{伟大的那么,更大然后或等于,等于,小于或等于,少于}私人比较类型 _compareType;私人日期时间_fromDate;私人日期时间_toDate;私有字符串_propertyNameToCompare;public DateCompareValidationAttribute(CompareType compareType, string message, string compareWith = ""){_compareType = 比较类型;_propertyNameToCompare = compareWith;ErrorMessage = 消息;}#region IClientValidatable 成员///<总结>///生成客户端验证规则///</总结>公共 IEnumerableGetClientValidationRules(ModelMetadata 元数据,ControllerContext 上下文){ValidateAndGetCompareToProperty(metadata.ContainerType);var rule = new ModelClientValidationRule();rule.ErrorMessage = 错误消息;rule.ValidationParameters.Add("comparetodate", _propertyNameToCompare);rule.ValidationParameters.Add("comparetype", _compareType);rule.ValidationType = "比较";收益回报规则;}#endregion受保护的覆盖 ValidationResult IsValid(object value, ValidationContext validationContext){//必须覆盖 IsValid 方法.如果您有任何服务器站点验证的逻辑,请将其放在这里.返回 ValidationResult.Success;}///<总结>///验证 compare-to 属性是否存在且类型正确并返回此属性///</总结>///<param name="containerType">容器对象的类型</param>///<returns></returns>私有 PropertyInfo ValidateAndGetCompareToProperty(类型容器类型){var compareToProperty = containerType.GetProperty(_propertyNameToCompare);if (compareToProperty == null){string msg = string.Format("{0} 的设计时使用无效.在 {2} 中找不到属性 {1}", this.GetType().FullName, _propertyNameToCompare, containerType.FullName);抛出新的 ArgumentException(msg);}if (compareToProperty.PropertyType != typeof(DateTime) && compareToProperty.PropertyType != typeof(DateTime?)){string msg = string.Format("{0} 的设计时使用无效.{2} 的属性 {1} 的类型不是 DateType", this.GetType().FullName, _propertyNameToCompare, containerType.FullName);抛出新的 ArgumentException(msg);}返回 compareToProperty;}}

    注意:如果要验证时间长度,请向构造函数添加另一个参数并更改此特定类型比较的枚举数

  2. 将属性添加到字段如下:
    [DateCompareValidation(DateCompareValidationAttribute.CompareType.GreatherThenOrEqualTo, "This Date must be on or after another date", compareWith: "AnotherDate")]

  3. 记下您生成的 html 是如何更改的.它应该包括您的验证消息、比较日期的字段名称等.生成的参数将以data-val-compare"开头.您在 GetClientValidationRules 方法中设置 ValidationType="compare" 时定义了此比较".

  4. 现在您需要匹配的 javascript 代码:添加验证适配器和验证方法.我在这里使用了匿名方法,但您不必这样做.我建议将此代码放在单独的 javascript 文件中,以便此文件与您的属性类一起成为一个控件,可以在任何地方使用.

<块引用>

$.validator.unobtrusive.adapters.add('比较',['比较日期','比较类型'],功能(选项){options.rules['compare'] = options.params;options.messages['compare'] = options.message;});

$.validator.addMethod("compare", function (value, element, parameters) {//value 是输入的实际值//元素是字段本身,包含值(以防值不够)var errMsg = "";//验证参数以确保每个用法都正确如果(parameters.comparetodate == 未定义){errMsg = "无法执行比较验证:未找到 comparetodate 参数";警报(错误消息);返回假;}if (parameters.comparetype == undefined) {errMsg = "无法执行比较验证:未找到比较类型参数";警报(错误消息);返回假;}var compareToDateElement = $('#' + parameters.comparetodate).get();if (compareToDateElement.length == 0) {errMsg = "无法执行比较验证:要比较的元素" + parameters.comparetodate + "未找到";警报(错误消息);返回假;}如果 (compareToDateElement.length > 1) {errMsg = "无法执行比较验证:要与 id 比较的元素多于一个" + parameters.comparetodate + " found";警报(错误消息);返回假;}//调试器;if (value && !isNaN(Date.parse(value))) {//仅验证包含有效日期的值.对于无效的日期和空白,应使用非自定义验证//获取要比较的日期var compareToDateValue = $('#' + parameters.comparetodate).val();if (compareToDateValue && !isNaN(Date.parse(compareToDateValue))) {//如果要比较的日期不是有效日期,则不验证它开关(参数.比较类型){案例GreatherThen":返回新日期(值)>新日期(比较日期值);案例GreatherThenOrEqualTo":return new Date(value) >= new Date(compareToDateValue);案例等于":return new Date(value) == new Date(compareToDateValue);案例LessThenOrEqualTo":return new Date(value) <= new Date(compareToDateValue);案例'LessThen':返回新日期(值)<新日期(比较日期值);默认:{errMsg = "无法执行比较验证:'" + parameters.comparetype + "' 对 comparetype 参数无效";警报(错误消息);返回假;}}返回真;}别的返回真;}别的返回真;});

这仅负责客户端不显眼的验证.如果您需要服务器端,则必须在 isValid 方法的覆盖中有一些逻辑.此外,您可以使用反射来使用显示属性等生成错误消息,并使消息参数可选.

Lets say I have a StartDate and an EndDate and I wnt to check if the EndDate is not more then 3 months apart from the Start Date

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);
    }
}

and I would like to implement this into my validation

[DateCompare("StartDate", "EndDate", ErrorMessage = "The Deal can only be 3 months long!")]

I know I get an error here... but how can I do this sort of business rule validation in asp.net mvc

解决方案

It's a late answer but I wanted to share it for others outhere. Here's how I've done it so that everything is validated using unobtrusive client validation:

  1. Create an attribute class:

    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;
    }
    }
    

    Note: if you want to validate length of time, add another parameter to the constractor and change enumerator for this specific type of comparsion

  2. Add the attributes to the field as folows:
    [DateCompareValidation(DateCompareValidationAttribute.CompareType.GreatherThenOrEqualTo, "This Date must be on or after another date", compareWith: "AnotherDate")]

  3. Take a note how your generated html is changed. It should include your validation message, field name for the compare-to date, etc. The generated parms would start with "data-val-compare". You defined this "compare" when you set ValidationType="compare" in GetClientValidationRules method.

  4. Now you need matching javascript code: to add an validation adapter and validation method. I used anonimous method here, but you don't have to. I recommend placing this code in a separate javascript file so that this file together with your attribute class become like a control and could be used anywhere.

$.validator.unobtrusive.adapters.add( 'compare', ['comparetodate', 'comparetype'], function (options) { options.rules['compare'] = options.params; options.messages['compare'] = options.message; } );

$.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;
});

This takes care only of client-side unobtrusive validation. If you need server side, you'd have to have some logic in the override of isValid method. Also, you can use Reflection to generate error message using display attributes, etc and make the message argument optional.

这篇关于比较日期 DataAnnotations Validation asp.net mvc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆