MVC 3.0 - 不显眼的客户端验证不适用于自定义属性

问题描述:

我是mvc 3.0和jquery的新手。我试图在客户端和服务器端使用自定义验证属性验证'日期'。它在服务器端运行良好,但无法使其在客户端工作。MVC 3.0 - 不显眼的客户端验证不适用于自定义属性

上午使用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; } 

有几个问题我可以用你的代码中看到。第一招:

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

在你有一对夫妇的问题,以及客户端。在您的验证方法中,您似乎在做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); 
    } 
} 
+0

非常感谢Darin,它的工作:) – HKGR 2012-02-21 05:32:22

+0

@DarinDimitrov什么将代替''错误信息到这里来''因为我总是得到相同的错误,而不是模型中定义的错误? – 2015-05-15 09:57:15

+0

好的。了解。它将是'String.Format(ErrorMessage,metadata.GetDisplayName(),this.Min)' – 2015-05-15 10:27:47