Validation rules¶
Supported data types¶
Valit provides validation rules for plenty different data types with full support for Nullable<T>
. The supported data types are:
Boolean
Byte
DateTime
DateTimeOffset
Decimal
Double
Float
Guid
IEnumerable<T>
Int16
Int32
Int64
SByte
String
TimeSpan
UInt16
UInt32
UInt64
Available validation rules¶
Because of differences between particular data types, each one contains its own set of available validation rules. However, there are two general extensions which can be applied on any type you want:
Satisifies<T>(Predicate<T>)
- checks whether given predicate returnstrue
.Required<T>()
- checks whether given reference type is notnull
.
Below you can find the full list of available validation rules for supported data types.
Note
null
either on validated property or given value always results rule returning false
Boolean¶
IsTrue(bool|bool?)
- checks whetherbool|bool?
property is equal totrue
.IsFalse(bool|bool?)
- checks whetherbool|bool?
property is equal tofalse
.IsEqualTo(bool|bool?)
- checks whetherbool|bool?
property is equal to given value.Required()
- checks whetherbool?
property is notnull
.
Byte¶
IsEqualTo(byte|byte?)
- checks whetherbyte|byte?
property is equal to given value.IsGreaterThan(byte|byte?)
- checks whetherbyte|byte?
property is greater than given value.IsGreaterThanOrEqualTo(byte|byte?)
- checks whetherbyte|byte?
property is greater than or equal to given value.IsLessThan(byte|byte?)
- checks whetherbyte|byte?
property is less than given value.IsLessThanOrEqualTo(byte|byte?)
- checks whetherbyte|byte?
property is less than or equal to given value.IsNonZero()
- checks whetherbyte|byte?
property is not a zero.Required()
- checks whetherbyte?
property is notnull
.
DateTime¶
IsAfter(DateTime|DateTime?)
- checks whetherDateTime|DateTime?
property is after (greater than) given value.IsAfterOrSameAs(DateTime|DateTime?)
- checks whetherDateTime|DateTime?
property is after or same as (greater than or equal to) given value.IsAfterNow()
- checks whetherDateTime|DateTime?
property is after (greater than)DateTime.Now
.IsAfterUtcNow()
- checks whetherDateTime|DateTime?
property is after (greater than)DateTime.UtcNow
.IsBefore(DateTime|DateTime?)
- checks whetherDateTime|DateTime?
property is before (less than) given value.IsBeforeOrSameAs(DateTime|DateTime?)
- checks whetherDateTime|DateTime?
property is before or same as (less than or equal to) given value.IsBeforeNow()
- checks whetherDateTime|DateTime?
property is before (less than)DateTime.Now
.IsBeforeUtcNow()
- checks whetherDateTime|DateTime?
property is before (less than)DateTime.UtcNow
.IsSameAs(DateTime|DateTime?)
- checks whetherDateTime|DateTime?
property is same as (equal to) given value.Required()
- checks whetherDateTime?
property is notnull
.
DateTimeOffset¶
IsAfter(DateTimeOffset|DateTimeOffset?)
- checks whetherDateTimeOffset|DateTimeOffset?
property is after (greater than) given value.IsAfterOrSameAs(DateTimeOffset|DateTimeOffset?)
- checks whetherDateTimeOffset|DateTimeOffset?
property is after or same as (greater than or equal to) given value.IsAfterNow()
- checks whetherDateTimeOffset|DateTimeOffset?
property is after (greater than)DateTime.Now
.IsAfterUtcNow()
- checks whetherDateTimeOffset|DateTimeOffset?
property is after (greater than)DateTime.UtcNow
.IsBefore(DateTimeOffset|DateTimeOffset?)
- checks whetherDateTimeOffset|DateTimeOffset?
property is before (less than) given value.IsBeforeOrSameAs(DateTimeOffset|DateTimeOffset?)
- checks whetherDateTimeOffset|DateTimeOffset?
property is before or same as (less than or equal to) given value.IsBeforeNow()
- checks whetherDateTimeOffset|DateTimeOffset?
property is before (less than)DateTime.Now
.IsBeforeUtcNow()
- checks whetherDateTimeOffset|DateTimeOffset?
property is before (less than)DateTime.UtcNow
.IsSameAs(DateTimeOffset|DateTimeOffset?)
- checks whetherDateTimeOffset|DateTimeOffset?
property is same as (equal to) given value.Required()
- checks whetherDateTimeOffset?
property is notnull
.
Decimal¶
IsEqualTo(decimal|decimal?)
- checks whetherdecimal|decimal?
property is equal to given value.IsGreaterThan(decimal|decimal?)
- checks whetherdecimal|decimal?
property is greater than given value.IsGreaterThanOrEqualTo(decimal|decimal?)
- checks whetherdecimal|decimal?
property is greater than or equal to given value.IsLessThan(decimal|decimal?)
- checks whetherdecimal|decimal?
property is less than given value.IsLessThanOrEqualTo(decimal|decimal?)
- checks whetherdecimal|decimal?
property is less than or equal to given value.IsNonZero()
- checks whetherdecimal|decimal?
property is not a zero.IsNegative()
- checks whetherdecimal|decimal?
property is negative (less than zero).IsPositive()
- checks whetherdecimal|decimal?
property is positive (greater than zero).Required()
- checks whetherdecimal?
property is notnull
.
Double¶
IsEqualTo(double|double?)
- checks whetherdouble|double?
property is equal to given value.IsGreaterThan(double|double?)
- checks whetherdouble|double?
property is greater than given value.IsGreaterThanOrEqualTo(double|double?)
- checks whetherdouble|double?
property is greater than or equal to given value.IsLessThan(double|double?)
- checks whetherdouble|double?
property is less than given value.IsLessThanOrEqualTo(double|double?)
- checks whetherdouble|double?
property is less than or equal to given value.IsNonZero()
- checks whetherdouble|double?
property is not a zero.IsNegative()
- checks whetherdouble|double?
property is negative (less than zero).IsPositive()
- checks whetherdouble|double?
property is positive (greater than zero).IsNaN()
- checks whetherdouble|double?
property isdouble.NaN
.IsNumber()
- checks whetherdouble|double?
property is notdouble.NaN
.Required()
- checks whetherdouble?
property is notnull
.
Float¶
IsEqualTo(float|float?)
- checks whetherfloat|float?
property is equal to given value.IsGreaterThan(float|float?)
- checks whetherfloat|float?
property is greater than given value.IsGreaterThanOrEqualTo(float|float?)
- checks whetherfloat|float?
property is greater than or equal to given value.IsLessThan(float|float?)
- checks whetherfloat|float?
property is less than given value.IsLessThanOrEqualTo(float|float?)
- checks whetherfloat|float?
property is less than or equal to given value.IsNonZero()
- checks whetherfloat|float?
property is not a zero.IsNegative()
- checks whetherfloat|float?
property is negative (less than zero).IsPositive()
- checks whetherfloat|float?
property is positive (greater than zero).IsNaN()
- checks whetherfloat|float?
property isfloat.NaN
.IsNumber()
- checks whetherfloat|float?
property is notfloat.NaN
.Required()
- checks whetherfloat?
property is notnull
.
Guid¶
IsEqualTo(Guid|Guid?)
- checks whetherGuid|Guid?
property is equal to given value.IsNotEmpty()
- checks whetherGuid|Guid?
property is notGuid.Empty
.Required()
- checks whetherGuid?
property is notnull
.
IEnumerable<T>¶
MinItems(int)
- checks whether collection contains at least given number of elements.MaxItems(int)
- checks whether collection contains at most given number of elements.
Int16¶
IsEqualTo(short|short?)
- checks whethershort|short?
property is equal to given value.IsGreaterThan(short|short?)
- checks whethershort|short?
property is greater than given value.IsGreaterThanOrEqualTo(short|short?)
- checks whethershort|short?
property is greater than or equal to given value.IsLessThan(short|short?)
- checks whethershort|short?
property is less than given value.IsLessThanOrEqualTo(short|short?)
- checks whethershort|short?
property is less than or equal to given value.IsNonZero()
- checks whethershort|short?
property is not a zero.IsNegative()
- checks whethershort|short?
property is negative (less than zero).IsPositive()
- checks whethershort|short?
property is positive (greater than zero).Required()
- checks whethershort?
property is notnull
.
Int32¶
IsEqualTo(int|int?)
- checks whetherint|int?
property is equal to given value.IsGreaterThan(int|int?)
- checks whetherint|int?
property is greater than given value.IsGreaterThanOrEqualTo(int|int?)
- checks whetherint|int?
property is greater than or equal to given value.IsLessThan(int|int?)
- checks whetherint|int?
property is less than given value.IsLessThanOrEqualTo(int|int?)
- checks whetherint|int?
property is less than or equal to given value.IsNonZero()
- checks whetherint|int?
property is not a zero.IsNegative()
- checks whetherint|int?
property is negative (less than zero).IsPositive()
- checks whetherint|int?
property is positive (greater than zero).Required()
- checks whetherint?
property is notnull
.
Int64¶
IsEqualTo(long|long?)
- checks whetherlong|long?
property is equal to given value.IsGreaterThan(long|long?)
- checks whetherlong|long?
property is greater than given value.IsGreaterThanOrEqualTo(long|long?)
- checks whetherlong|long?
property is greater than or equal to given value.IsLessThan(long|long?)
- checks whetherlong|long?
property is less than given value.IsLessThanOrEqualTo(long|long?)
- checks whetherlong|long?
property is less than or equal to given value.IsNonZero()
- checks whetherlong|long?
property is not a zero.IsNegative()
- checks whetherlong|long?
property is negative (less than zero).IsPositive()
- checks whetherlong|long?
property is positive (greater than zero).Required()
- checks whetherlong?
property is notnull
.
SByte¶
IsEqualTo(sbyte|sbyte?)
- checks whethersbyte|sbyte?
property is equal to given value.IsGreaterThan(sbyte|sbyte?)
- checks whethersbyte|sbyte?
property is greater than given value.IsGreaterThanOrEqualTo(sbyte|sbyte?)
- checks whethersbyte|sbyte?
property is greater than or equal to given value.IsLessThan(sbyte|sbyte?)
- checks whethersbyte|sbyte?
property is less than given value.IsLessThanOrEqualTo(sbyte|sbyte?)
- checks whethersbyte|sbyte?
property is less than or equal to given value.IsNonZero()
- checks whethersbyte|sbyte?
property is not a zero.IsNegative()
- checks whethersbyte|sbyte?
property is negative (less than zero).IsPositive()
- checks whethersbyte|sbyte?
property is positive (greater than zero).Required()
- checks whethersbyte?
property is notnull
.
String¶
Email()
- checks whetherstring
property is a correct email address.IsEqualTo(string)
- checks whetherstring
property is equal to given value.Matches(string)
- checks whetherstring
property matches given regex.MinLength(int)
- checks whetherstring
property has at least given number of characters.MaxLength(int)
- checks whetherstring
property has at most given number of characters.Required()
- checks whetherstring
property is notnull
.
TimeSpan¶
IsEqualTo(TimeSpan|TimeSpan?)
- checks whetherTimeSpan|TimeSpan?
property is equal to given value.IsGreaterThan(TimeSpan|TimeSpan?)
- checks whetherTimeSpan|TimeSpan?
property is greater than given value.IsGreaterThanOrEqualTo(TimeSpan|TimeSpan?)
- checks whetherTimeSpan|TimeSpan?
property is greater than or equal to given value.IsLessThan(TimeSpan|TimeSpan?)
- checks whetherTimeSpan|TimeSpan?
property is less than given value.IsLessThanOrEqualTo(TimeSpan|TimeSpan?)
- checks whetherTimeSpan|TimeSpan?
property is less than or equal to given value.IsNonZero()
- checks whetherTimeSpan|TimeSpan?
property is not a zero.Required()
- checks whetherTimeSpan?
property is notnull
.
UInt16¶
IsEqualTo(ushort|ushort?)
- checks whetherushort|ushort?
property is equal to given value.IsGreaterThan(ushort|ushort?)
- checks whetherushort|ushort?
property is greater than given value.IsGreaterThanOrEqualTo(ushort|ushort?)
- checks whetherushort|ushort?
property is greater than or equal to given value.IsLessThan(ushort|ushort?)
- checks whetherushort|ushort?
property is less than given value.IsLessThanOrEqualTo(ushort|ushort?)
- checks whetherushort|ushort?
property is less than or equal to given value.IsNonZero()
- checks whetherushort|ushort?
property is not a zero.IsNegative()
- checks whetherushort|ushort?
property is negative (less than zero).IsPositive()
- checks whetherushort|ushort?
property is positive (greater than zero).Required()
- checks whetherushort?
property is notnull
.
UInt32¶
IsEqualTo(uint|uint?)
- checks whetheruint|uint?
property is equal to given value.IsGreaterThan(uint|uint?)
- checks whetheruint|uint?
property is greater than given value.IsGreaterThanOrEqualTo(uint|uint?)
- checks whetheruint|uint?
property is greater than or equal to given value.IsLessThan(uint|uint?)
- checks whetheruint|uint?
property is less than given value.IsLessThanOrEqualTo(uint|uint?)
- checks whetheruint|uint?
property is less than or equal to given value.IsNonZero()
- checks whetheruint|uint?
property is not a zero.IsNegative()
- checks whetheruint|uint?
property is negative (less than zero).IsPositive()
- checks whetheruint|uint?
property is positive (greater than zero).Required()
- checks whetheruint?
property is notnull
.
UInt64¶
IsEqualTo(ulong|ulong?)
- checks whetherulong|ulong?
property is equal to given value.IsGreaterThan(ulong|ulong?)
- checks whetherulong|ulong?
property is greater than given value.IsGreaterThanOrEqualTo(ulong|ulong?)
- checks whetherulong|ulong?
property is greater than or equal to given value.IsLessThan(ulong|ulong?)
- checks whetherulong|ulong?
property is less than given value.IsLessThanOrEqualTo(ulong|ulong?)
- checks whetherulong|ulong?
property is less than or equal to given value.IsNonZero()
- checks whetherulong|ulong?
property is not a zero.IsNegative()
- checks whetherulong|ulong?
property is negative (less than zero).IsPositive()
- checks whetherulong|ulong?
property is positive (greater than zero).Required()
- checks whetherulong?
property is notnull
.
Validating nested objects¶
Sometimes there could be need to validate nested objects. You can do this by creating IValitator
(more details here). Let’s say we have the following model:
public class OrderModel
{
public AddressModel Address { get; set; }
}
public class AddressModel
{
public string City { get; set; }
public string Street { get; set; }
}
We’d like to be sure that City
and Street
in our OrderModel
are not null
. To do that we have to create the following valitator:
public class AdressModelValitator : IValitator<AddressModel>
{
public IValitResult Validate(AddressModel @object, IValitStrategy strategy = null)
=> ValitRules<AddressModel>
.Create()
.Ensure(am => am.City, _ => _
.Required())
.Ensure(am => am.City, _ => _
.Required())
.For(@object)
.Validate();
}
Then we can validate our OrderModel
using the created valitator:
void ValidateModel(OrderModel model)
{
var result = ValitRules<OrderModel>
.Create()
.Ensure(m => m.Address, new AdressModelValitator())
.For(model)
.Validate();
}
Validating collections¶
Using Valit you can also easily validate collections. Let’s assume that you have following model:
public class ContactModel
{
public IEnumerable<string> Emails { get; set; }
}
We’d like to check whether each item in Emails
list is neither null
nor string.Empty
and is also valid email address. To validate collections use EnsureFor
:
void Validate(ContactModel model)
{
var result = ValitRules<ContactModel>
.Create()
.WithStrategy(picker => picker.FailFast)
.EnsureFor(m => m.Emails, _=>_
.Required()
.WithMessage("Email list is empty")
.Email()
.WithMessage("Email list contains incorrect addresses"))
.For(model)
.Validate();
}
Conditional rules¶
In some cases there might be need to apply certain validation rules only if specific conditions are fulfilled. Valit allows you to do this using When()
extension which can be applied on each rule. Let’s say we have the following model:
public class RegisterModel
{
public string Email { get; set; }
public string Password { get; set; }
public string CompanyName { get; set; }
public bool IsCompanyMember { get; set; }
}
We’d like CompanyName
to be required only if the user belongs to some company (defined by IsCompanyMemeber
). Of course, we could create two separate validators to handle both scenarios, but a lot of code would be duplicated. That’s where conditional rules come into play:
void ValidateModel(RegisterModel model)
{
var result = ValitRules<RegisterModel>
.Create()
.Ensure(m => m.Email, _=>_
.Required()
.Email())
.Ensure(m => m.Password, _=>_
.Required()
.MinLength(10))
.Ensure(m => m.CompanyName, _=>_
.Required()
.When(m => m.IsCompanyMember))
.For(model)
.Validate();
}
Using When()
we created simple validation condition which solves the issue.
Note
You can apply as much conditions as you want on each rule. If so, they will be merged into one condition using logical AND operator.
Tagging rules¶
Each validation rule can have its own set of tags. Tags are used for defining subset of rules that will be checked during the validation process. To add tags to the validation rule use Tag()
extension. The code below presents the example usage:
public class RegisterModel
{
public string Email { get; set; }
public int Age { get; set; }
}
void ValidateModel(RegisterModel model)
{
IValitRules<RegisterModel> valitRules = ValitRules<RegisterModel>
.Create()
.Ensure(m => m.Email, _=>_
.Required()
.Tag("A")
.Email()
.Tag("A", "B"))
.Ensure(m => m.Age, _=>_
.IsGreaterThan(16)
.Tag("B"))
.For(model);
IValitResult result1 = valitRules.Validate("A"); // Checks Required, Email
IValitResult result2 = valitRules.Validate("B"); //Checks Email, IsGreaterThan
IValitResult result3 = valitRules.Validate("A", "B"); //Checks all rules
}
As you see in the example above, instead of invoking the Validate()
right after the For()
method, we assigned the rules to the variable. Then, using the Validate()
overload which accepts tags, we created three different validation processes. That gave as a lot of flexibility by creating one general set of validation rules instead of three separated. It is important that set of tags passed to the Validate()
method defines that each rule must have at least one of them, NOT all.
Validate()
method has also an overload which accepts Predicate<IValitRule<TModel>>
:
var result1 = rules.Validate(rule => rule.Tags.Any(tag => tag == "A")); // Checks Required, Email
ValitRules<T>
object also provides three methods for getting set of your validation rules. The methods are:
GetAllRules()
- gets all rules.GetTaggedRules()
- gets rules which has at least one tag.GetUntaggedRules()
- gets rules with no tags.
Of course if you want to get rules with the specific tags, you can use Linq for that purpose like in the example below:
IEnumerable<IValitRule<RegisterModel>> rulesOnlyWithATag= ValitRules<RegisterModel>
.Create()
.Ensure(m => m.Email, _=>_
.Required().Tag("A")
.Email().Tag("B"))
.GetTaggedRules()
.Where(rule => rule.Tags.Contains("A")); // only Required method is selected
Having the set of rules, you can use them for instantiating new ValitRules<T>
object using Create()
method overload:
void ValidateModel(RegisterModel model, IEnumerable<IValitRule<RegisterModel>> rulesOnlyWithATag)
{
IValitResult result = ValitRules<RegisterModel>
.Create(rulesOnlyWithATag)
.For(model)
.Validate(); // validates the model using only Required rule on Email property
}