简体   繁体   中英

Custom Validation Attribute for three levels deep model

Hi I have a situation in witch I have to create some custom validation attributes because the way my model is created.The model looks something like this:

public class EvaluationFormDataContract
{
    public int StudentAssignmentInstanceId { get; set; }

    public int EvaluationType { get; set; }


    public List<CategoriesOnEvaluationDataContract> Categories { get; set; }
}

  public class CategoriesOnEvaluationDataContract
{
    public string Memo { get; set; }

    public int CategoryId { get; set; }

    public List<QuestionsOnEvalCategoryDataContract> Questions { get; set; }

    // Fields needed for validation
    public bool? HasMemo { get; set; }

    public bool MemoIsMandatory { get; set; }
}

    public class QuestionsOnEvalCategoryDataContract
{
    public string Memo { get; set; }

    public string Grade { get; set; }

    public int QuestionId { get; set; }

    // Fields needed for validation
    public bool HasGrade { get; set; }

    public bool HasMemo { get; set; }

    public bool ShowOnlyMemo { get; set; }
}

As it can be seem the model is composed two levels deep. And I will have to validate starting from the second level , where I will check if the model HasMemo and if MemoIsMandatory.

The third validation should be done at the 3rd level where I have to check if it HasGrade and HasMemo.

Normaly if it were up to me I would split this in three separate calls to the server but we are depending on an legacy project and for the moment I have to make this work.

The post action will be called via an ajax call and will have all this data into it.

Now my question is where should I add the validation attribute?

Should it be added at the top on Categories , making it directly responsible for all the levels of the model?

Or I should place it on each model and find a way to make the data binder aware of it? If so how can I do this?

You can do both. If you implement System.ComponentModel.DataAnnotations.IValidatableObject interface at the top-most level, you can do whatever you want with the properties in the entire graph and return the errors.

public class EvaluationFormDataContract : IValidatableObject
{
        // All properties go here

        public IEnumerable<ValidationResult> Validate(
                                 ValidationContext validationContext)
        {
            if (// do what you want)
                yield return new ValidationResult("message");
        }
}

Or, you can apply attributes at the lower levels and automatically binding takes care of validating the properties in the graph. You don't need to do anything special.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM