我已经创建了一个自定义验证属性,如下所示:
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; }
效果很好,但是我还希望能够添加客户端验证?
答案 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();
}
答案 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.