So I have web app that is registering users and business partners.
This is how my models look like
public class UserModel : IValidatableObject
{
//here are some properties and methods that I am using in Validate method
public CompanyModel Company { get; set; } //this is user Company
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.UserWithEmailExists())
yield return new ValidationResult("Email already exists", new[] { "Email" });
if (this.UserWithUsernameExists())
yield return new ValidationResult("Username already exists", new[] { "Username" });
}
}
public class CompanyModel : IValidatableObject
{
//again here are some properties that i am using in Validate
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.Phone == null && this.Mobile == null)
yield return new ValidationResult("The Phone field is required", new[] { "Phone" });
}
}
//this is the model passed to the view
public sealed class RegistrationModel : UserModel, IValidatableObject
{
public new IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.Password != this.PasswordValidation)
yield return new ValidationResult("Ponovite prejšnji vnos", new[] { "PasswordValidation" });
}
}
The problem is: When I submit my form Validate in CompanyModel is called and Validate in RegistrationModel too. But I want also Validate in UserModel to be called...
UPDATE: I solved the first problem: These are the models after upgrading :)
public class UserModel : IValidatableObject
{
//here are some properties and methods that I am using in Validate method
public CompanyModel Company { get; set; } //this is user Company
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.UserWithEmailExists())
yield return new ValidationResult("Email already exists", new[] { "Email" });
if (this.UserWithUsernameExists())
yield return new ValidationResult("Username already exists", new[] { "Username" });
}
}
public class CompanyModel : IValidatableObject
{
//again here are some properties that i am using in Validate
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.Phone == null && this.Mobile == null)
yield return new ValidationResult("The Phone field is required", new[] { "Phone" });
}
}
//this is the model passed to the view
public sealed class RegistrationModel : UserModel, IValidatableObject
{
public override new IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//this is needed so that UserModel validation executes
foreach (var result in base.Validate(validationContext))
{
yield return result;
}
if (this.Password != this.PasswordValidation)
yield return new ValidationResult("Ponovite prejšnji vnos", new[] { "PasswordValidation" });
}
}
Now validation works fine. I just do not know why Validate in CompanyModel executes two times??. Any suggestion?
When you override a method in a base class, the method in that base class is not explicitly called. You need to do it yourself, so in the Validate
function in RegistrationModel, add a call to the Validate
function in the base UserModel class.
base.Validate(validationContext);
However, as you use yield return
in your validators, that makes the Validate
function an iterator, so it must be iterated through in order for everything to work properly. As per this question, the full solution is to use this code in your RegistrationModel.Validate
function:
foreach (var result in base.Validate(validationContext))
{
yield return result;
}