【问题标题】:MVC 3.0 - unobtrusive client side validation is not working for custom attributesMVC 3.0 - 不显眼的客户端验证不适用于自定义属性
【发布时间】:2012-02-20 16:36:39
【问题描述】:

我是 mvc 3.0 和 jquery 的新手。我正在尝试使用自定义验证属性在客户端和服务器端验证“日期”。它在服务器端运行良好,但无法使其在客户端运行。

我正在使用 mvc 3.0、jquery、IE 7.0。 我们需要在 MVC 3.0 的 global.ascx 中注册任何东西吗?

请让我知道我哪里错了。 TIA。

这是我的代码:

验证属性

 public class FutureDateAttribute : ValidationAttribute, IClientValidatable
 {
        private const string DateFormat = "mm/dd/yyyy";
        private const string DefaultErrorMessage = "'{0}' must be a date between {1:d} and current date.";

        public DateTime Min { get; set; }
        public DateTime Max { get; set; }

        public FutureDateAttribute(string min)
            : base(DefaultErrorMessage)
        {
            Min = ParseDate(min);
            Max = DateTime.Now;
        }

        public override bool IsValid(object value)
        {
            if (value == null || !(value is DateTime))
            { return true; }
            DateTime dateValue = (DateTime)value;
            return Min <= dateValue && dateValue <= Max;
        }

        private static DateTime ParseDate(string dateValue)
        {
            return DateTime.ParseExact(dateValue, DateFormat, System.Globalization.CultureInfo.InvariantCulture);
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(System.Globalization.CultureInfo.CurrentCulture, ErrorMessageString, name, Min);
        }

        public class ModelClientValidationFutureDateRule : ModelClientValidationRule
        {
            public ModelClientValidationFutureDateRule(string errorMessage,
                DateTime min)
            {
                ErrorMessage = errorMessage;
                ValidationType = "futuredate";
                ValidationParameters["min"] = min.ToString("mm/dd/yyyy");
                ValidationParameters["max"] = DateTime.Now.ToString("mm/dd/yyyy");
            }
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationFutureDateRule("Error message goes here", this.Min);
            yield return rule;
        }

jquery

(function ($) {
$.validator.addMethod('futuredate', function (value, element, param) {
    if (!value) return false;
    var min = $(param.min).val();
    var max = $(param.max).val();
    if (value < min || value > max) {
        return false;
    }
    return true;
});

$.validator.unobtrusive.adapters.add(
  'futuredate', ['min', 'max'],
  function (options) {
      var params = {
          min: options.params.min,
          max: options.params.max
      };

      options.rules['futuredate'] = params;
      if (options.message) {
          options.messages['futuredate'] = options.message;
      }
  });
} (jQuery)); 

参考文献

<script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
 <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
 ///reference path="jquery-1.5.1.min.js" />
 ///reference path="jquery.validate.js" />
 ///reference path="jquery-ui-1.8.11.js" />
  ///reference path="jquery.validate.unobtrusive.min.js" />
 ///reference path="jquery.validate-vsdoc.js" />

型号:

[DisplayName("Assigned Date :")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
    [Required(ErrorMessage = "Assigned Date is required")]
    [DataType(DataType.Date)]
    [FutureDate("12/31/1899", ErrorMessage = "'{0}' must be a date between {1:d} and current date.")]
    public DateTime? AssignedDate { get; set; }

【问题讨论】:

    标签: jquery asp.net-mvc-3 custom-attributes unobtrusive-validation


    【解决方案1】:

    我可以看到您的代码存在几个问题。第一个:

    ValidationParameters["min"] = min.ToString("mm/dd/yyyy");
    ValidationParameters["max"] = DateTime.Now.ToString("mm/dd/yyyy");
    

    一定是:

    ValidationParameters["min"] = min.ToString("MM/dd/yyyy");
    ValidationParameters["max"] = DateTime.Now.ToString("MM/dd/yyyy");
    

    因为mm 表示分钟而不是几个月。

    同样的评论:

    private const string DateFormat = "mm/dd/yyyy";
    

    必须是:

    private const string DateFormat = "MM/dd/yyyy";
    

    在客户端,您也有几个问题。在您的futuredate 验证方法中,您似乎在做var min = $(param.min).val();,它转换为var min = $('12/31/1899').val();,这显然没有多大意义。您必须先将这些值解析为 javascript Date 实例,然后才能进行比较。

    以下是我的建议:

    @model MyViewModel
    
    <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <script type="text/javascript">
        (function ($) {
            var parseDate = function (str) {
                var m = str.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
                return (m) ? new Date(m[3], m[1] - 1, m[2]) : null;
            };
    
            $.validator.addMethod('futuredate', function (value, element, param) {
                if (!value) return false;
    
                var min = parseDate(param.min);
                var max = parseDate(param.max);
                var current = parseDate(value);
    
                if (min == null || max == null || current == null) {
                    return false;
                }
    
                return (current >= min && current <= max);
            });
    
            $.validator.unobtrusive.adapters.add('futuredate', ['min', 'max'], function (options) {
                var params = {
                    min: options.params.min,
                    max: options.params.max
                };
    
                options.rules['futuredate'] = params;
                if (options.message) {
                    options.messages['futuredate'] = options.message;
                }
            });
        } (jQuery));
    </script>
    
    @using (Html.BeginForm())
    {
        @Html.LabelFor(x => x.AssignedDate)
        @Html.EditorFor(x => x.AssignedDate)
        @Html.ValidationMessageFor(x => x.AssignedDate)
        <button type="submit">OK</button>
    }
    

    这是我用于测试用例的验证属性的完整代码:

    public class FutureDateAttribute : ValidationAttribute, IClientValidatable
    {
        private const string DateFormat = "MM/dd/yyyy";
        private const string DefaultErrorMessage = "'{0}' must be a date between {1:d} and current date.";
    
        public DateTime Min { get; set; }
        public DateTime Max { get; set; }
    
        public FutureDateAttribute(string min)
            : base(DefaultErrorMessage)
        {
            Min = ParseDate(min);
            Max = DateTime.Now;
        }
    
        public override bool IsValid(object value)
        {
            if (value == null || !(value is DateTime))
            { return true; }
            DateTime dateValue = (DateTime)value;
            return Min <= dateValue && dateValue <= Max;
        }
    
        private static DateTime ParseDate(string dateValue)
        {
            return DateTime.ParseExact(dateValue, DateFormat, System.Globalization.CultureInfo.InvariantCulture);
        }
    
        public override string FormatErrorMessage(string name)
        {
            return String.Format(System.Globalization.CultureInfo.CurrentCulture, ErrorMessageString, name, Min);
        }
    
        public class ModelClientValidationFutureDateRule : ModelClientValidationRule
        {
            public ModelClientValidationFutureDateRule(string errorMessage,
                DateTime min)
            {
                ErrorMessage = errorMessage;
                ValidationType = "futuredate";
                ValidationParameters["min"] = min.ToString("MM/dd/yyyy");
                ValidationParameters["max"] = DateTime.Now.ToString("MM/dd/yyyy");
            }
        }
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationFutureDateRule("Error message goes here", this.Min);
            yield return rule;
        }
    }
    

    还有模特:

    public class MyViewModel
    {
        [DisplayName("Assigned Date :")]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [Required(ErrorMessage = "Assigned Date is required")]
        [DataType(DataType.Date)]
        [FutureDate("12/31/1899", ErrorMessage = "'{0}' must be a date between {1:d} and current date.")]
        public DateTime? AssignedDate { get; set; }
    }
    

    和控制器:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View(new MyViewModel
            {
                AssignedDate = DateTime.Now.AddDays(2)
            });
        }
    
        [HttpPost]
        public ActionResult Index(MyViewModel model)
        {
            return View(model);
        }
    }
    

    【讨论】:

    • @DarinDimitrov 什么会代替"Error message goes here",因为我总是遇到相同的错误,而不是模型中定义的错误?
    • 好的。了解。它将是String.Format(ErrorMessage, metadata.GetDisplayName(), this.Min)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多