自定义验证适用于服务器端但不适用于客户端asp mvc 5

时间:2015-02-24 00:24:16

标签: javascript jquery asp.net-mvc validation

我有一个自定义验证类来验证日期。它适用于服务器端,但不适用于客户端。我无法触发jquery方法来进行检查。我想我的适配器或验证器可能连接不正确。 的 P.S。我可以让非自定义客户端验证工作(例如[必需]),而不是我的自定义验证

查看模型

public class HomePageViewModel
{
    [Required]
    public string SearchQuery { get; set; }

    [DisplayName("Date")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
    [ClassDate(ErrorMessage = "Class date must be today or later.")]
    public DateTime ClassDate { get; set; }
}

验证类。

public class ClassDateAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value == null) // ok, just use todays date day
        {
            return true;
        }

        DateTime toValidate = (DateTime) value;

        if (toValidate.Day < DateTime.Now.Day) // if they are looking for classes in the past
        {
            return false;
        }
        return true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata,
        ControllerContext context)
    {
        var classDateRule = new ModelClientValidationRule();
        classDateRule.ErrorMessage = "test error message";
        classDateRule.ValidationType = "classdate"; 

        yield return classDateRule;
    }
}

Javascript代码。

$(function () {
$(".datefield").datepicker();
var now = new Date();

var day = ("0" + now.getDate()).slice(-2);
var month = ("0" + (now.getMonth() + 1)).slice(-2);

var today = (month) + "/" + (day) + "/" + now.getFullYear();

$('.datefield').val(today);


$.validator.unobtrusive.adapters.addSingleVal("classdate");

$.validator.addMethod("classdate", function(value) {
    if (value) {
        //do something to test date here
        //if date is today or later
        return true;
    }
    return false;
});
});

这是我认为的元素。

 @Html.TextBoxFor(model => model.ClassDate, new { @class = "datefield form-control", @id = "ClassDate", @type = "date", name = "ClassDate" })
 @Html.ValidationMessageFor(model => model.ClassDate, "", new { @class = "text-danger" })

2 个答案:

答案 0 :(得分:2)

您未获得客户端验证的主要问题是您使用$.validator.unobtrusive.adapters.addSingleVal("classdate");addSingleVal()用于验证模型中的其他属性。它必须是$.validator.unobtrusive.adapters.addBool("classdate");

由于您使用的是jQueryUI日期选择器,因此可以使用

阻止选择小于今天日期的日期
$(.datefield).datepicker({
  minDate: 0
});

这里有很多代码没有意义(参见下面的附注),应该是

属性定义

[DisplayName("Date")]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
[NotLessThanToday]
public DateTime ClassDate { get; set; }

验证属性

public class NotLessThanTodayAttribute : ValidationAttribute, IClientValidatable
{
  private const string _DefaultErrorMessage = "The property {0} cannot be less than todays date";

  public NotLessThanTodayAttribute() : base(_DefaultErrorMessage)
  {
  }

  public override string FormatErrorMessage(string name)
  {
    return string.Format(ErrorMessageString, name);
  }

  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    if (value == null)
    {
      return ValidationResult.Success; // ??
    }
    DateTime date = DateTime.Today;
    if (DateTime.TryParse((string)value, out date))
    {
      if (date < DateTime.Today)
      {
        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
      }
    }
    else
    {
      // not a valid date
    }
    return base.IsValid(value, validationContext);
  }

  public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
  {
    var clientValidationRule = new ModelClientValidationRule()
    {
      ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
      ValidationType = "notlessthantoday"
    };
    return new[] { clientValidationRule };
  }
}

脚本

$.validator.addMethod("notlessthantoday", function (value, element, params) {
  if (!this.optional(element)) {
    var date = new Date(value);
    var today = new Date();
    return date > today;
  }
  return true; // ??
});

$.validator.unobtrusive.adapters.addBool("notlessthantoday");

旁注

  1. ApplyFormatInEditMode = true与。一起使用 [DataType(DataType.Date)]@Html.EditorFor()来呈现 浏览器HTML5 datepicker。这里没有必要,如果你这样做了 使用它,格式字符串需要"{0:yyyy-MM-dd}"(ISO 格式)
  2. 您当前的验证属性仅检查日期日期 比今天少。 if (toValidate.Day < DateTime.Now.Day) 含义1/1/2016有效(1小于24)。
  3. 脚本var now = new Date(); ..... $('.datefield').val(today); 毫无意义,并覆盖模型中的值(用户输入 日期,您发布并返回视图,您的代码将重置日期 回到今天的价值!)。如果你想显示今天的日期,那么 在将模型传递给视图之前,请在模型中设置该值 (model.ClassDate = Datetime.Today;
  4. 您在帮助程序中设置(或尝试)以下属性: @id="ClassDate", @type="date", name="ClassDate"。 html助手 无论如何,将id属性设置为id="ClassDate"。该 type="date"不是必需的(用于渲染浏览器HTML5 datepicker)并设置name属性 什么都没有(幸运的是它没有用,因为你试图给它 它是“ClassDate”的另一个名称,绑定会失败)

答案 1 :(得分:-1)

...的document.ready

1)加载整个网页后执行。

2)通常,用于初始化dom元素上的事件(如.click,.change,.select)。这是有道理的,因为您通常不能将事件附加到尚未加载的dom元素。

3)一般来说,功能不会进入document.ready。这是有道理的,因为函数通常会被事件调用。

当然,所有事情都有例外,但这些都是非常好的经验法则。