Reputation: 379
I have a question regarding property validation, however, I haven't yet been able to find an appropriate answer.
I have the following classes
public class IndexViewModel
{
public Film Film { get; set; }
public ReviewModel Review { get; set; }
}
public class ReviewModel
{
[RequiredIf // only fire if 'Genre' is equal to Genre.Horror]
public string Text { get; set; }
}
public class Film
{
public string Title { get; set; }
public Director Director { get; set; }
public Genre Genre { get; set; }
}
public class Director
{
public string Name { get; set; }
}
public enum Genre
{
Horror,
Thriller,
SciFi,
Drama
}
Is it possible to add a [RequiredIf]
attribute on the Text
property in ReviewModel
which fires validation based on the value of Genre
in the Film
model. Any Help would be greatly appreciated.
Upvotes: 1
Views: 1870
Reputation: 663
Put it in your business layer.
[RequiredIf // only fire if 'Genre' is equal to Genre.Horror
]
if you need to put it on your model, you might as well implement
System.ComponentModel.IValidatableObject
and then use the ObjectValidator to validate it.
However based on experience, I do basic attribute decoration on my model such as Required and StringLength, so that asp.net MVC can pick up on, and dump the important business rule in my service layer, since the validation logic is rarely that simple and usually require external data elements like additional calls to the database.
it really depends on your use cases. I like to keep my data classes dumb because i expect the data to be moved around and thus the validation logic would be lost during serialization i.e JSON serialization.
Upvotes: 1
Reputation: 10879
I wouldn't recommend using validation attributes when the properties that need to be validated aren't in the class it's associated with. I haven't seen a RequiredIfAttribute
implementation that cuts across models like that. (Here's a good one from a different question.)
What about a simple implementation of IValidatableObject
? It would be quite clear, and MVC will check for it when constructing the model.
public class IndexViewModel : IValidatableObject
{
public Film Film { get; set; }
public ReviewModel Review { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Film.Genre == Genre.Horror && string.IsNullOrWhiteSpace(Review.Text))
{
yield return new ValidationResult(
"Please provide a review for this film.",
new string[] { nameof(Review.Text) });
}
}
}
Upvotes: 3