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
}
}
The following are the common Data Validation Types:Code Check. Range Check. Format Check.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With