Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

validation of model on data not entered by user

I have this ViewModel (simplified):

public class ResponseViewModel {

    public QuestionViewModel Question { get; set; }
    public string Answer { get; set; }
}

public class QuestionViewModel {

    public string Text { get; set; }
    public string Description { get; set; }
    public bool IsRequired { get; set; }
}

QuestionViewModel is mapped from my DAL entity Question which is a straightforward mapping from:

public class Question {

    public int Id { get; set; }
    public string Text { get; set; }
    public string Description { get; set; }
    public bool IsRequired { get; set; }
}

I want to be able to make Answer Required if Question.IsRequired is true. However after the postback Only The property Answer is filled (of course).

What is the best way to go here? I would like to be able to create a validation attribute but don't know how to achieve this.

UPDATE:

I tried to make it work by using ModelBinding but until now no succes. What I have done:

public class EntityModelBinder : DefaultModelBinder
  protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        // IF I DO IT HERE I AM TOO EARLY
    }
  protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);
        // IF I DO IT HERE I AM TOO LATE. VALIDATION ALREADY TOOK PLACE
    }
}
like image 380
amaters Avatar asked Sep 10 '13 06:09

amaters


People also ask

What are the 3 types of data validation?

The following are the common Data Validation Types:Code Check. Range Check. Format Check.

How do you validate data models?

7 Steps to Model Development, Validation and TestingCreate the development, validation and testing data sets. Use the training data set to develop your model. Compute statistical values identifying the model development performance. Calculate the model results to the data points in the validation data set.


2 Answers

Perhaps a RequiredÌf attribute is what you need. There are several questions on StackOverflow regarding this. One of them can be found here: RequiredIf Conditional Validation Attribute.

Darin also points to a blogpost on MSDN containing an implementation of the RequiredIf attribute.

With this attribute your view model would become something like:

public class ResponseViewModel {

    public QuestionViewModel Question { get; set; }

    [RequiredIf("Question.IsRequired", true, "This question is required.")]
    public string Answer { get; set; }
}

I'm not sure if the implementations I gave support properties on complex types (Question.IsRequired for example) but with some modification it should be possible.

like image 121
Henk Mollema Avatar answered Sep 19 '22 04:09

Henk Mollema


You can use IValidatableObject to perform validation at class level (in this case, ResponseViewModel), in order to check the answer's validity according to Question.IsRequired :

public class ResponseViewModel : IValidatableObject
{
    public QuestionViewModel Question { get; set; }
    public string Answer { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Question.IsRequired && string.IsNullOrEmpty(Answer))
        {
            yield return new ValidationResult("An answer is required.");
        }
    }
}

However, Question.IsRequired must have a valid value during validation process. You can do this by putting it in your view as an hidden input :

@Html.HiddenFor(m => m.Question.IsRequired)

The default model binder will get the right value and perform validation correctly.

like image 42
Réda Mattar Avatar answered Sep 22 '22 04:09

Réda Mattar