javascript - ASP.NET MVC 实现自定义验证器使用 IClientValidatable

标签 javascript asp.net-mvc asp.net-mvc-3 razor unobtrusive-validation

我问类似的问题here但在这个问题中我使用了另一个实现,正是this way以下代码显示了我的实现:

型号:

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);
}, '');

和我的_布局页面(母版页)

<!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>

当然,在编辑和创建 View 页面中,其他脚本源如下:

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

创建页面 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 种方式,但都没有给出真正的答案。

最佳答案

你搞砸了你的脚本包含。在您的 _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 脚本添加到布局中,以防它在许多 View 中使用,否则您可以将其添加到 View 中:

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

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

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

关于javascript - ASP.NET MVC 实现自定义验证器使用 IClientValidatable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8284207/

相关文章:

javascript - 通过使用 Safari 更改 window.location 下载文件

asp.net-mvc - ASP.NET MVC AJAX onError处理

c# - AuthorizeAttribute 和参数

asp.net-mvc - MVC3和Table以及如何生成

jquery - 为什么 Ajax.BeginForm 会替换我的整个页面?

javascript - 创建自定义折叠面板 - Extjs 4.0a2

带有 ajax 的 Javascript 回调函数

javascript - 如何使用 JADE 显示和访问各个键值

c# - ASP.NET MVC 输出缓存 "thread safe"

asp.net-mvc - 使用Razor View 引擎输出Json