Tutorial :Entity validation with different scenario



Question:

On the assumption that I have Entity with couple of fields. Some fields are required at some specific state but others only on further/other state.

public class Entity  {      //Required always      public SomeReference {}        //Required in specific situation/scenario      public OtherReference {}  }  

How to achieve that scenario with some known validation framework or how to do it by my self?

For help: Udi Dahan has some thoughts on this. http://www.udidahan.com/2007/04/30/generic-validation/


Solution:1

I have a solution that I am using at the moment. I use Fluent validation and am still getting used to it. I can give you an example of a simple scenario I have. maybe it helps. I have a user class, with a address Object property. At some point, I want to only validate the User details(name, email, password, etc) and at another state I want to validate the user address(first line, postcode, etc).

Classes look like this:

public class User {      public virtual string Name { get; set; }      public virtual string Email { get; set; }      public virtual string Password { get; set; }      public virtual Address Address { get; set; }          }    public class Address {      public virtual string Address1 { get; set; }      public virtual string PostCode { get; set; }  }  

I then have two (simplfied) validators, one for an address and one for a user:

    public AddressValidator() {          RuleFor(address => address.Address1)              .NotNull()              .WithMessage("Please enter the first line of your address");            RuleFor(address => address.PostCode)              .NotNull()              .WithMessage("Please enter your postcode")              .Matches(UK_POSTCODE_REGEX)              .WithMessage("Please enter a valid post code!");      }        public UserValidator() {          RuleFor(user => user.FirstName)              .NotNull()              .WithMessage("Please provide a first name")              .Length(3, 50)              .WithMessage("First name too short");            RuleFor(user=> user.Password)              .Length(8, 50)              .WithMessage("Password is too short");      }  

I then create a Model Validator, so for example, say we have a form where the user enters an address, we create a AddressModelValidator, and can re-use the validators we have written:

    public AddressModelValidator()  {          RuleFor(user => user.id)              .NotNull()              .WithMessage("An error has occured, please go back and try again");            RuleFor(user => user.Address).SetValidator(new AddressValidator());      }  

So, with some thought, you can really create some nice models, and reduce your validation code duplication!


Solution:2

My preferernce is to localize common validation functions such as email and date validations into a ValidationService class that I can pass my object into. For the rest though I tend to put the validation into the class itself. If I am using LINQ to SQL then I can create a Validate() method on my object which LINQ to SQL will call prior to saving the object to the db like this:

public void Validate()  {      if(!IsValid)          throw new ValidationException("Rule violations prevent saving");  }    public bool IsValid  {      get { return GetRuleViolations().Count() == 0;}  }    public IEnumerable<RuleViolation> GetRuleViolations()  {      if(this.TermID == 0)          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(1), "agreeWithTerms");        if(ValidationService.ValidateDate(this.Birthdate.ToString()))          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(2), "birthDate");        if (!(Username.Length >= ConfigurationService.GetMinimumUsernameLength()) ||          !(Username.Length <= ConfigurationService.GetMaximumUsernameLength()))          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(5), "username");        if(ValidationService.ValidateUsernameComplexity(Username))          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(6), "username");        if (AccountID == 0 && ObjectFactory.GetInstance<IAccountRepository>().UsernameExists(this.Username))          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(7), "username");        if (!ValidationService.ValidateEmail(Email))          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(8), "email");        if (AccountID == 0 && ObjectFactory.GetInstance<IAccountRepository>().EmailExists(this.Email))          yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(9), "email");        yield break;  }  

Read here for a full understanding of this: http://nerddinnerbook.s3.amazonaws.com/Part3.htm


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »