I have a list of checkboxes that a user can select. I am saving the list using Entity Framework Code First. These are my models:
public class Company {
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Type> Types { get; set; }
}
public class Type {
public int ID { get; set; }
public string Name { get; set; }
}
A company has a list of types that belong to it. Some of these types depend on eachother. For example: my type with the name BMI depends on the types with the names length and weight. To enforce this I am currently using jQuery but I would like to handle it in the model. I am thinking about something like this:
[Dependency("BMI", DependsOn = { "length", "weight" })]
Is there a way to enforce dependencies within a list using Data Annotations? If there's not: what would be the best way to enforce these dependencies without having to use jQuery?
Attempt one
So, I started working on a solution. Here's my code so far:
class TypeDependencyAttribute : ValidationAttribute
{
public string Dependant { get; set; }
public string[] Dependencies { get; set; }
public TypeDependencyAttribute(string dependant, string[] dependencies)
{
Dependant = dependant;
Dependencies = dependencies;
}
public override bool IsValid(object value)
{
List<Isala.Models.Metingen.Type> list = value as List<Isala.Models.Metingen.Type>;
if (list.Any(p => p.Naam == Dependant))
{
foreach(var dependency in Dependencies){
if (!list.Any(p => p.Naam == dependency))
{
return false;
}
}
}
return true;
}
}
And in my model:
[TypeDependency("BMI", new string {"Lengte", "Gewicht"})]
[DataMember(IsRequired = true)]
public ICollection<Type> Types { get; set; }
This brings me to my next problem. According to this answer on another question you can't pass an array to an validation attribute. This renders my solution quite useless.
Attempt two
Next try, let's loose the array and do it like this:
[TypeDependency("BMI", "Lengte")]
[TypeDependency("BMI", "Gewicht")]
[DataMember(IsRequired = true)]
public ICollection<Type> Types { get; set; }
Well, you can't, according to this errormessage:
"Duplicate 'TypeDependency' attribute"
Appearently, the compiler doesn't like this either. Now, there ís another solution I can think of, but I don't like it:
[TypeDependent]
[DataMember(IsRequired = true)]
public ICollection<Type> Types { get; set; }
Attribute:
class TypeDependencyAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
List<Isala.Models.Metingen.Type> list = value as List<Isala.Models.Metingen.Type>;
if (list.Any(p => p.Naam == "BMI"))
{
if (!list.Any(p => p.Naam == "Lengte") && !list.Any(p => p.Naam == "Gewicht"))
{
return false;
}
}
return true;
}
}
Is this my only option? Can I work around this duplicate attribute error (I need multiple dependencies, BMI isn't the only one).