asp mvc core 3用于自定义属性验证的客户端验证

时间:2019-10-18 12:25:02

标签: c# asp.net-core

我已经创建了一个自定义验证属性,如下所示:

public class UniqueTitleAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(
           object value, ValidationContext validationContext)
        {
            var context = (MyDBContext)validationContext.GetService(typeof(MyDBContext));
            var entity = context.Pages.SingleOrDefault(e => e.Title == value.ToString());

            if (entity != null)
            {
                return new ValidationResult(GetErrorMessage(value.ToString()));
            }
            return ValidationResult.Success;
        }

        public string GetErrorMessage(string title)
        {
            return $"Title {title} is already in use.";
        }
    }

以及模型中的

[UniqueTitle]
public string Title { get; set; }

效果很好,但是我还希望能够添加客户端验证?

2 个答案:

答案 0 :(得分:0)

在自定义验证属性中,实现IClientModelValidator接口并创建一个AddValidation方法。在AddValidation方法中,添加data-属性以进行验证,如下所示:

public class UniqueTitleAttribute : ValidationAttribute, IClientModelValidator
{
    protected override ValidationResult IsValid(
       object value, ValidationContext validationContext)
    {
        var context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));
        var entity = context.Articles.SingleOrDefault(e => e.Title == value.ToString());

        if (entity != null)
        {
            return new ValidationResult(GetErrorMessage(value.ToString()));
        }
        return ValidationResult.Success;
    }

    public void AddValidation(ClientModelValidationContext context)
    {
        Type obj = typeof(Article);
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        MergeAttribute(context.Attributes, "data-val", "true");
        MergeAttribute(context.Attributes, "data-val-uniquetitle", GetErrorMessage());
    }
    private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
    {
        if (attributes.ContainsKey(key))
        {
            return false;
        }

        attributes.Add(key, value);
        return true;
    }

    public string GetErrorMessage()
    {
        return $"The title is already in use.";
    }
    public string GetErrorMessage(string title)
    {
        return $"Title {title} is already in use.";
    }
}

向jQuery验证库添加方法。它使用addMethod()方法来指定我们自己的验证功能。验证功能接收在标题文本框中输入的值。然后执行验证并返回布尔值。

<div class="row">
<div class="col-md-4">
    <form method="post" asp-action="CreateArticle">
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>

        <div class="form-group">
            <label asp-for="Title" class="control-label"></label>
            <input asp-for="Title" class="form-control" />
            <span asp-validation-for="Title" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Author" class="control-label"></label>
            <input asp-for="Author" class="form-control" />
            <span asp-validation-for="Author" class="text-danger"></span>
        </div>

        <div class="form-group">
            <input type="submit" value="Create" class="btn btn-primary" />
        </div>
    </form>
</div>
</div>

@section Scripts
{
   @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
  <script type="text/javascript">
    var titlelist = @Html.Raw(Json.Serialize(ViewBag.TitleList));
    $.validator.addMethod("uniquetitle",
    function (value, element, param) {

        if (titlelist.includes(value)) {
            return false;
        }
        else {
            return true;
        }
    });
    $.validator.unobtrusive.adapters.addBool("uniquetitle");
  </script>
}

在视图的Get方法中将TitleList保存在ViewBag中,以便从js判断标题是否正在使用:

public IActionResult CreateArticle()
    {
        ViewBag.TitleList = _context.Articles.Select(a => a.Title).ToList();
        return View();
    }

结果: enter image description here

答案 1 :(得分:-2)

You have to use jquery and unobtrusive client side validation so fetch those urls in 
your page.

Use like 
<label asp-for="Name"></label>
<input asp-for="Name"/>
<span asp-validation-for="Name"></span>

Here i have taken example of Name as validation will fire on Name property but you can 
change property on which you want.