我正在使用ASP.NET MVC 5并尝试使用在控制器post方法中实例化并从EF重新加载的视图模型对象的数据注释来进行自定义验证。从客户端发布时只填充少数模型属性,其余的使用EF重新加载。该模型很复杂,它的所有部分都实现了IValidatableObject。在正确加载所有内容后,Validate方法中的代码将触发新视图模型,但它不会对应用于模型的数据注释执行任何操作。
因此,例如,如果我的模型具有应用于字段的EmailAddress属性,则它在客户端上运行良好,但在针对新视图模型进行验证时会在服务器端忽略它。如何使用Validate方法将数据注释考虑在内?
以下是控制器操作的代码......
[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult SignUp(SignUpEM em) {
if (em == null) {
return RedirectToAction(MVC.Sheet.Index());
}
SignUpSheet signUpSheet = db.GetSignUpSheet(em.SheetId);
SignUpEM newEM = Map.ToSignUpEM(signUpSheet);
foreach (var sourceField in em.Fields) {
FieldEM targetField = newEM.Fields.FirstOrDefault(f => f.FieldDefId == sourceField.FieldDefId && f.Id == sourceField.Id);
if (targetField.FieldType.IsEditable()) {
if (targetField.FieldType.IsBoolean()) {
((BooleanFieldEM)targetField).BooleanValue = ((BooleanFieldEM)sourceField).BooleanValue;
}
else {
targetField.Value = sourceField.Value;
}
targetField.SetFullyLoaded();
}
}
// This line is here to simulate an invalid value passed into an email field.
newEM.Fields[0].Value = "invalid";
newEM.SetFullyLoaded();
ModelState.Clear();
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(newEM, new ValidationContext(newEM, null, null), validationResults, true);
foreach (var result in validationResults) {
if (result == null) { continue; } // otherwise we need to avoid duplicates.
if (result.MemberNames.Count() == 0)
ModelState.AddModelError(String.Empty, result.ErrorMessage);
else
foreach (var name in result.MemberNames)
ModelState.AddModelError(name, result.ErrorMessage);
}
if (!ModelState.IsValid) {
return View(newEM);
}
SignUp su = Map.ToSignUp(em);
db.AddSignUp(su);
return RedirectToAction(MVC.SignUp.SignUp(em.SheetId));
}
这是SignUpEM的验证码......
private bool fullyLoaded;
internal void SetFullyLoaded() {
fullyLoaded = true;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (fullyLoaded) {
foreach (var f in Fields)
foreach (var vr in f.Validate(validationContext))
yield return vr;
if (ListIntro == null)
yield return new ValidationResult("ListIntro is required for now.");
}
}
FieldEM的验证码......
private bool fullyLoaded;
internal void SetFullyLoaded() {
fullyLoaded = true;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (fullyLoaded) {
if (Optional == false && String.IsNullOrEmpty(Value)) {
string message = string.Format("{0} is required.", DisplayName);
yield return new ValidationResult(message);
}
}
}