ASP.NET MVC实现自定义validation器使用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; } }
自定义validation器:
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>
当然在编辑和创build视图页面的其他脚本源如下:
<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>
创build页面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>
我尝试所有的实现和这里一样,但是在客户端不工作,需要回发,我没有任何其他的实现,例如像这样在global.asax中注册,有没有人知道呢? 我很困惑,我尝试了两种方法,但都没有给出真实的答案。
你弄糟了你的脚本包含。 在你的_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.js
和jquery.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>
这是你在视图中唯一的脚本。 您应该从“编辑和创build视图”页面中删除任何其他jquery.*
脚本包含。
备注:您还会注意到我已经从布局中删除了所有Microsoft*.js
脚本。 它们已经过时,不应该再被用在ASP.NET MVC 3中。