11

我问类似的问题here但在这个问题上我用另一种实现方式,正是this way以下代码显示我的实现:ASP.NET MVC实现自定义的验证器使用IClientValidatable

型号:

public class Department { 

    public long Id { get; set; } 

    [IsDateAfter("Date2", true, ErrorMessage = "O My")] 
    public DateTime Date1 { get; set; } 
    public DateTime Date2 { get; set; } 
    public string Name1 { get; set; } 
    public string Name2 { get; set; } 

} 

定制验证器:

public sealed class IsDateAfter : ValidationAttribute, IClientValidatable { 

    private readonly string testedPropertyName; 
    private readonly bool allowEqualDates; 

    public IsDateAfter(string testedPropertyName, bool allowEqualDates = false) 
    { 
     this.testedPropertyName = testedPropertyName; 
     this.allowEqualDates = allowEqualDates; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext 
validationContext) { 
     var propertyTestedInfo = 
validationContext.ObjectType.GetProperty(this.testedPropertyName); 
     if (propertyTestedInfo == null) { 
      return new ValidationResult(string.Format("unknown property 
{0}", this.testedPropertyName)); 
     } 

     var propertyTestedValue = 
propertyTestedInfo.GetValue(validationContext.ObjectInstance, null); 

     if (value == null || !(value is DateTime)) { 
      return ValidationResult.Success; 
     } 

     if (propertyTestedValue == null || !(propertyTestedValue is 
DateTime)) { 
      return ValidationResult.Success; 
     } 

     // Compare values 
     if ((DateTime)value >= (DateTime)propertyTestedValue) { 
      if (this.allowEqualDates) { 
       return ValidationResult.Success; 
      } 
      if ((DateTime)value > (DateTime)propertyTestedValue) { 
       return ValidationResult.Success; 
      } 
     } 

     return new 
ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
    } 

    public IEnumerable<ModelClientValidationRule> 
GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { 
     var rule = new ModelClientValidationRule { 
      ErrorMessage = this.ErrorMessageString, 
      ValidationType = "isdateafter" 
     }; 
     rule.ValidationParameters["propertytested"] = 
this.testedPropertyName; 
     rule.ValidationParameters["allowequaldates"] = 
this.allowEqualDates; 
     yield return rule; 
    } 
} 

脚本:

$.validator.unobtrusive.adapters.add(
'isdateafter', ['propertytested', 'allowequaldates'], function (options) { 
    options.rules['isdateafter'] = options.params; 
    options.messages['isdateafter'] = options.message; 
}); 
$.validator.addMethod("isdateafter", function (value, element, params) { 
alert(params.propertytested); 
var startdatevalue = $('input[name="' + params.propertytested + '"]').val(); 
if (!value || !startdatevalue) return true; 
return (params.allowequaldates) ? Date.parse(startdatevalue) <= Date.parse(value) : 
Date.parse(startdatevalue) < Date.parse(value); 
}, ''); 

和我的_layout页(主页)

<!DOCTYPE html> 
<html> 
<head> 
<title>@ViewBag.Title</title> 
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> 
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"> 
</script> 
<script src="@Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"> 
</script> 
<script src="@Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"> 
</script> 
<script src="@Url.Content("~/Scripts/MicrosoftMvcValidation.js")" 
type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 
type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"> 
</script> 
<script src="@Url.Content("~/Scripts/jQuery.IsDateAfter.js")" 
type="text/javascript"></script> 
</head> 
<body> 
<div class="page"> 
    <div id="header"> 
     <div id="title"> 
      <h1> 
       My MVC Application</h1> 
     </div> 
     <div id="logindisplay"> 
      @Html.Partial("_LogOnPartial") 
     </div> 
     <div id="menucontainer"> 
      <ul id="menu"> 
     <li>@Html.ActionLink("Departments", "Index", "Department")</li> 
      </ul> 
     </div> 
    </div> 
    <div id="main"> 
     @RenderBody() 
    </div> 
    <div id="footer"> 
    </div> 
</div> 
</body> 
</html> 
当然,在编辑的

,并创建查看页面其他脚本源如下:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> 
</script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" 
type="text/javascript"></script> 

Create Page Dom的一部分:

<fieldset> 
<legend>Department</legend> 
<div class="editor-label"> 
<label for="Date1">Date1</label> 
</div> 
<div class="editor-field"> 
<input id="Date1" class="text-box single-line valid" type="text" value="" name="Date1" 
data-val-required="The Date1 field is required." data-val-isdateafter- 
propertytested="Date2" data-val-isdateafter-allowequaldates="False" data-val- 
isdateafter="O My" data-val="true"> 
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg- 
    for="Date1"></span> 
</div> 
<div class="editor-label"> 
<label for="Date2">Date2</label> 
</div> 
<div class="editor-field"> 
<input id="Date2" class="text-box single-line valid" type="text" value="" name="Date2" 
data-val-required="The Date2 field is required." data-val="true"> 
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg- 
for="Date2"></span> 
</div> 

我尝试所有的实施是相同的here但在客户端无法正常工作,需要回传,我没有任何其他的实现,例如在Global.asax中 注册像this,请问任何人都知道吗?我真的很困惑,我尝试了2种方式,但没有人给出真正的答案。

回答

9

你弄乱了你的脚本包含。在你_layout已包含在顺序以下脚本:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jQuery.IsDateAfter.js")" type="text/javascript"></script> 

现在很明显jquery.validate.min.jsjquery.validate.js代表相同的脚本,首先是缩小的版本。但是由于您没有包含jquery.validate.unobtrusive.js脚本(这在您的视图中稍后完成),您的自定义jQuery.IsDateAfter.js脚本将包含错误,因为它不会知道您正在使用的对象$.validator.unobtrusive.adapters。因此,这里是你的布局脚本应该是什么样子:

<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 

你也可以在末尾添加自定义jQuery.IsDateAfter.js脚本的布局,如果你的情况下,希望它在许多视图中使用,如果没有,你可以添加它到视图:

<script src="@Url.Content("~/Scripts/jQuery.IsDateAfter.js")" type="text/javascript"></script> 

这是你应该在视图中唯一的脚本。您应该从编辑和创建视图页面中删除任何其他jquery.*脚本包含。

备注:您还会注意到我已经从布局中删除了所有Microsoft*.js脚本。它们已经过时,不应该再用于ASP.NET MVC 3.

+2

我跟着这个,可以看到验证错误消息,而我编辑的表单很棒。一个奇怪的事情,它不停止形式发布,即使有无效的字段与适当的验证错误消息,但是服务器不承认ModelState.IsValid为false ...这是正常的行为还是我错过了什么? – afr0