自定义验证属性来检查我的模特属性之间的重复不点火 [英] Custom validation attribute to check for duplicates among my model properties is not firing
问题描述
我想自定义验证属性添加到我的模型,以检查是否有任何的答案包含重复。也就是说,如果在对任何字段相同的答案的用户类型,我想,当他们键入重复回答显示错误。
I want to add a custom validation attribute to my model to check if any of the answers contain duplicates. That is, if the user types in the same answer for any of the fields, I want to display an error when they type in a duplicate answer.
下面是我的模型:
public class SecurityQuestions
{
public int Question1Id { get; set; }
public int Question2Id { get; set; }
public int Question3Id { get; set; }
public int Question4Id { get; set; }
public int Question5Id { get; set; }
public int Question6Id { get; set; }
[UniqueAnswersOnly]
public string Answer1 { get; set; }
[UniqueAnswersOnly]
public string Answer2 { get; set; }
[UniqueAnswersOnly]
public string Answer3 { get; set; }
[UniqueAnswersOnly]
public string Answer4 { get; set; }
[UniqueAnswersOnly]
public string Answer5 { get; set; }
[UniqueAnswersOnly]
public string Answer6 { get; set; }
}
下面是我在自定义属性的尝试:
Here's my attempt at custom attribute:
public class UniqueAnswersOnly: ValidationAttribute, IClientValidatable
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
//Get a list of all properties that are marked with [UniqueAnswersOnly]
var props = validationContext.ObjectInstance.GetType().GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(UniqueAnswersOnly)));
var values = new HashSet<string>();
//Read the values of all other properties
foreach(var prop in props)
{
var pValue = (string)prop.GetValue(validationContext.ObjectInstance, null);
if (prop.Name!=validationContext.MemberName && !values.Contains(pValue))
{
values.Add(pValue);
}
}
if (values.Contains(value))
{
return new ValidationResult("Duplicate answer", new[] { validationContext.MemberName });
}
return null;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
ErrorMessage = metadata.DisplayName + " is required!",
ValidationType = "duplicateanswers"
};
yield return rule;
}
}
我现在遇到的问题是验证是,即使我在重复的答案进入SUCESSFUL。我还可以继续下一个对话框(我期待的验证,如果输入重复失败)。我想这是因为我的自定义属性不被解雇或打击,因为我加了断点,但没有被击中。
The problem I'm having now is the the validation is sucessful even though I enter in duplicate answers. I can still continue to next dialog (I am expecting validation to fail if duplicates are entered). I think it's because my custom attribute isn't being fired or hit because I added breakpoints but nothing is hit.
在我的控制器,我有如果(ModelState.IsValid){//继续下一个对话框}
和模型的状态不会返回有效。
In my controller, I have if(ModelState.IsValid) { //continue to next dialog}
and the model state does return valid.
推荐答案
您可以创建一个自定义的验证属性是这样的:
You could create a custom validation attribute like this:
public class UniqueAnswersOnly : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
//Get a list of all properties that are marked with [UniqueAnswersOnly]
var props = validationContext.ObjectInstance.GetType().GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(UniqueAnswersOnly)));
var values = new HashSet<string>();
//Read the values of all other properties
foreach(var prop in props)
{
var pValue = (string)prop.GetValue(validationContext.ObjectInstance);
if (prop.Name!=validationContext.MemberName && !values.Contains(pValue))
{
values.Add(pValue);
}
}
if (values.Contains(value))
{
return new ValidationResult("Duplicate answer", new[] { validationContext.MemberName });
}
return null;
}
}
和这里是一个测试用例:
and here is a test case:
public class SecurityQuestions
{
public int Question1Id { get; set; }
public int Question2Id { get; set; }
public int Question3Id { get; set; }
public int Question4Id { get; set; }
public int Question5Id { get; set; }
public int Question6Id { get; set; }
[UniqueAnswersOnly]
public string Answer1 { get; set; }
[UniqueAnswersOnly]
public string Answer2 { get; set; }
[UniqueAnswersOnly]
public string Answer3 { get; set; }
[UniqueAnswersOnly]
public string Answer4 { get; set; }
[UniqueAnswersOnly]
public string Answer5 { get; set; }
[UniqueAnswersOnly]
public string Answer6 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var questions = new SecurityQuestions();
questions.Answer1 = "Test";
questions.Answer2 = "Test";
questions.Answer3 = "Test3";
questions.Answer4 = "Test4";
questions.Answer5 = "Test5";
questions.Answer6 = "Test6";
var vc = new ValidationContext(questions, null, null);
var results = new List<ValidationResult>();
var validationResult = Validator.TryValidateObject(questions, vc, results, true);
}
}
编辑:
我创建了一个默认的MVC项目并添加当前的code。该验证的作品就好。
I created a default MVC project and added your current code. That validation works just fine.
我已将此添加到家居控制器:
I added this to the home controller:
public ActionResult AskQuestions()
{
var questions = new SecurityQuestions();
return View(questions);
}
[HttpPost]
public ActionResult CheckQuestions(SecurityQuestions questions)
{
if (ModelState.IsValid)
{
return View();
}
else
{
return HttpNotFound();
}
}
而AskQuestions看法是这样的:
And the AskQuestions view looks like this:
@model WebApplicationValidation.Models.SecurityQuestions
@{
ViewBag.Title = "AskQuestions";
}
<h2>AskQuestions</h2>
@using (Html.BeginForm("CheckQuestions", "Home",FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SecurityQuestions</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Question1Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Question1Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Question1Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Question2Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Question2Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Question2Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Question3Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Question3Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Question3Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Question4Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Question4Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Question4Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Question5Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Question5Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Question5Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Question6Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Question6Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Question6Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Answer1, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Answer1, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Answer1, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Answer2, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Answer2, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Answer2, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Answer3, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Answer3, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Answer3, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Answer4, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Answer4, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Answer4, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Answer5, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Answer5, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Answer5, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Answer6, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Answer6, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Answer6, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
如果我运行的应用程序的ModelState.IsValid()是假的,如果我输入两个相同的答案。和设置在验证程序断点表明,它是正在运行。
If I run the app the ModelState.IsValid() is false if I enter two identical answers. And setting a breakpoint in the validation routine shows that it's being run.
这篇关于自定义验证属性来检查我的模特属性之间的重复不点火的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!