首页 > 解决方案 > 我无法在 ASP.NET 应用程序上进行客户端验证

问题描述

我的问题

我尝试使用客户端验证创建自定义验证器。但是客户端验证端不起作用,我不明白为什么。

这是一个 .NET Core 3.1 应用程序。

我的代码

验证者:

public class ExcludeCharAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string _chars;
    public ExcludeCharAttribute(string chars)
        : base("{0} contains invalid character.")
    {
        _chars = chars;
    }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            var valueAsString = value.ToString();
            for (int i = 0; i < _chars.Length; i++)
            {
                if (valueAsString.Contains(_chars[i]))
                {
                    var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                    return new ValidationResult(errorMessage);
                }
            }
        }
        return ValidationResult.Success;
    }
    //new method  
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule();
        rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
        rule.ValidationParameters.Add("chars", _chars);
        rule.ValidationType = "exclude";
        yield return rule;
    }
}

为了测试,我创建了这个测试 dto:

public class TestDto
{
    [ExcludeChar("123456")]
    public string Prop1 { get; set; }

    [Required]
    public string Prop2 { get; set; }
}

和那种形式:

<div class="row">
    <div class="col-md-4">
        <form asp-action="TestValidator">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Prop1" class="control-label"></label>
                <input asp-for="Prop1" class="form-control" />
                <span asp-validation-for="Prop1" class="text-danger"></span>

                <label asp-for="Prop2" class="control-label"></label>
                <input asp-for="Prop2" class="form-control" />
                <span asp-validation-for="Prop2" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script src="~/js/validator.js"></script>
}

当然还有这个验证 js(validator.js):

$.validator.unobtrusive.adapters.addSingleVal("exclude", "chars");
$.validator.addMethod("exclude", function (value, element, exclude) {
    if (value) {
        for (var i = 0; i < exclude.length; i++) {
            if (jQuery.inArray(exclude[i], value) != -1) {
                return false;
            }
        }
    }
    return true;
});

发生什么事

测试时不运行客户端验证。检查代码时,我没有看到 Prop1 的任何 data-* 属性:

在此处输入图像描述

但是对于 Prop2 来说没关系。我认为这就是它不起作用的原因。

我测试的

测试了其他在线示例。

测试我加载了所有的JS:

在此处输入图像描述

测试脚本的 CDN 版本

我需要的

现在我不知道该怎么办。有人对缺少什么有想法吗?

谢谢你

标签: asp.net-mvcasp.net-corevalidation

解决方案


我复制了您的自定义验证代码并在我这边进行了测试,但效果很好,您能检查一下您的代码和我的代码之间的差异吗?我确定视图代码是相同的,并且在验证类中您可以检查使用包。

验证类:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace WebAppMvc.Models
{
    public class ExcludeCharAttribute : ValidationAttribute, IClientValidatable
    {
        private readonly string _chars;
        public ExcludeCharAttribute(string chars)
            : base("{0} contains invalid character.")
        {
            _chars = chars;
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                var valueAsString = value.ToString();
                for (int i = 0; i < _chars.Length; i++)
                {
                    if (valueAsString.Contains(_chars[i]))
                    {
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    }
                }
            }
            return ValidationResult.Success;
        }
        //new method  
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationParameters.Add("chars", _chars);
            rule.ValidationType = "exclude";
            yield return rule;
        }
    }
}

模型:

using System.ComponentModel.DataAnnotations;

namespace WebAppMvc.Models
{
    public class UserModel
    {
        [Key]
        [ExcludeChar("123456")]
        public string id { get; set; }
        public int userId { get; set; }
    }
}

这是我的控制器方法:

[HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create([Bind("id,userId")] UserModel user)
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }
            return View(user);
        }

这是视图:

@model WebAppMvc.Models.UserModel
<h4>Test</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="id" class="control-label"></label>
                <input asp-for="id" class="form-control" />
                <span asp-validation-for="id" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="userId" class="control-label"></label>
                <input asp-for="userId" class="form-control" />
                <span asp-validation-for="userId" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

在此处输入图像描述


推荐阅读