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

发布于 2024-12-18 11:17:29 字数 6661 浏览 1 评论 0原文

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

模型:

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>

创建页面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 中注册 像这个,有人吗知道吗?我真的很困惑,我尝试了两种方法,但没有一个给出真正的答案。

I ask similar question here but in this question I use another implementation, exactly this way the following codes show my implementations:

Model:

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

}

Custom Validator:

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

Script:

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

And My _Layout page (Master page)

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

of course in Edit And Create View pages the other script source are as following:

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

A part of 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>

I try All of implementation be the same as here but that not work in client side and need to postback, I don't have any other implementation for example register in global.asax
like this, Does any one know about it? I really confused, I tried 2 way but none of them give the true answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不气馁 2024-12-25 11:17:29

你把你的脚本内容弄乱了。在您的 _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 中使用。

You have messed up your script inclusions. In your _Layout you have included the following scripts in that order:

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

Now obviously jquery.validate.min.js and jquery.validate.js represents the same script, the first being the minified version. But since you haven't included the jquery.validate.unobtrusive.js script (this is done much later in your view), your custom jQuery.IsDateAfter.js script will contain errors since it will not know about the $.validator.unobtrusive.adapters object that you are using. So here's how the scripts in your layout should look:

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

You could also add your custom jQuery.IsDateAfter.js script to the layout at the end if you wish in case it is used in many views and if not you could add it to the view:

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

That's the only script you should have in the view. You should remove any other jquery.* script inclusions from your Edit And Create View pages.

Remark: you will also notice that I have removed all Microsoft*.js scripts from your Layout. They are obsolete and should no longer be used in ASP.NET MVC 3.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文