我正在向代码添加自定义验证属性,它可以在服务器端完美运行。但是,在客户端,方法和适配器已注册,但从未调用验证功能。
我正在使用MVC在.NET Core 2.2中工作。我已经按照其他地方的建议删除了$(Document).Ready包装器,并验证了所有大小写是否匹配。
以下是MRE
测试验证属性:
public class TestValidationAttribute : ValidationAttribute, IClientModelValidator
{
public TestValidationAttribute(string name)
{
_name = name;
}
private string _name;
protected override ValidationResult IsValid(Object value, ValidationContext validationContext)
{
return new ValidationResult($"{_name} has been validated");
}
void IClientModelValidator.AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-testvalidation", $"{_name} has been validated client side");
context.Attributes.Add("data-val-testvalidation-name", _name);
}
}
模型:
public class TestModel
{
[TestValidation("Hello World!")]
[Display(Name = "Test Value")]
public string TestValue { get; set; }
}
视图:
<div class="form-group">
@using (Html.BeginForm())
{
<div class="row">
@Html.LabelFor(m => m.TestValue)
</div>
<div class="row">
@Html.EditorFor(m => m.TestValue)
</div>
<div class="row">
@Html.ValidationMessageFor(m => m.TestValue)
</div>
<div class="row">
<input type="submit" value="Submit" />
</div>
}
</div>
验证JS:
$(function ($) {
$.validator.addMethod('testvalidation',
function (value, element, params) {
return false;
});
$.validator.unobtrusive.adapters.add('testvalidation', ['name'],
function (options) {
options.rules['testvalidation'] = { name: options.params['name'] };
options.messages['testvalidation'] = options.messages;
});
}(jQuery));
生成的HTML:
<div class="form-group">
<form action="/" method="post"> <div class="row">
<label for="TestValue">Test Value</label>
</div>
<div class="row">
<input class="text-box single-line" data-val="true" data-val-testvalidation="Hello World! has been validated client side" data-val-testvalidation-name="Hello World!" id="TestValue" name="TestValue" type="text" value="" />
</div>
<div class="row">
<span class="field-validation-valid" data-valmsg-for="TestValue" data-valmsg-replace="true"></span>
</div>
<div class="row">
<input type="submit" value="Submit" />
</div>
<input name="__RequestVerificationToken" type="hidden" value="" /></form></div>
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2019 - WebApplication1 - <a href="/Home/Privacy">Privacy</a>
</div>
</footer>
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<script src="/js/testvalidation.js"></script>
<script src="/js/site.js?v=4q1jwFhaPaZgr8WAUSrux6hAuh0XDg9kPS3xIVq36I0"></script>
答案 0 :(得分:0)
我根据您的问题和代码创建了一个有效的示例。
public class TestModel
{
[TestValidation("Hello world!", ErrorMessage = "You did not write Hello world!.")]
[Display(Name = "Test Value")]
public string TestValue { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
public class TestValidationAttribute : ValidationAttribute, IClientModelValidator
{
private object _expectedValue;
public TestValidationAttribute(object expectedValue)
{
_expectedValue = expectedValue;
}
public override bool IsValid(object value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
return Equals(value, _expectedValue);
}
public void AddValidation(ClientModelValidationContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-testvalidation", ErrorMessage);
context.Attributes.Add("data-val-testvalidation-expectedvalue", _expectedValue.ToString());
}
}
请注意,jQuery验证在加载DOM之前先注册其规则。如果在DOM加载后尝试注册适配器,则将不会处理您的规则。因此,将其包装在一个自执行函数中。
$(function ($) {
$.validator.addMethod('testvalidation', function (value, element, params) {
var expectedValue = params.expectedvalue;
if (!expectedValue) return false;
var actual = element.value;
if (actual === expectedValue) return true;
return false;
});
$.validator.unobtrusive.adapters.add('testvalidation', ['expectedvalue'],
function (options) {
// Add validation rule for HTML elements that contain data-testvalidation attribute
options.rules['testvalidation'] = {
// pass the data from data-testvalidation-expectedvalue to
// the params argument of the testvalidation method
expectedvalue: options.params['expectedvalue']
};
// get the error message from data-testvalidation-expectedvalue
// so that unobtrusive validation can use it when validation rule fails
options.messages['testvalidation'] = options.message;
});
}(jQuery));
正确的脚本加载方式是
@section Scripts{
@Html.Partial("_ValidationScriptsPartial"); // Or instead like this:
<!--<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>-->
<!--<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js">-->
<script src="~/js/testvalidation.js"></script>
}
答案 1 :(得分:0)
您需要将options.params['name']
更改为options.params.name
。
这是一个简单的解决方法,如下所示:
<script>
$.validator.addMethod('testvalidation',
function (value, element, params) {
if (value == "") {
return false;
}
return true;
},"Please set a value");
$.validator.unobtrusive.adapters.add('testvalidation', ['name'],
function (options) {
console.log(options);
options.rules['testvalidation'] = { name: options.params.name};
console.log(options.rules['testvalidation']);
options.messages['testvalidation'] = options.message.messages;
});
</script>
答案 2 :(得分:0)
因此,事实证明,我的问题与代码无关,但我对验证的工作原理有所了解。我原以为它会在模糊时触发,但是直到提交后才会触发。