I have the below view models, which are used to represent a survey of questions, but they are structured into a more flattened grid to accommodate the default model binder.
// Main ViewModel for the Question View
public class SurveyRowList
{
...
public IList<SurveyRow> SurveyRowList { get; set; }
}
public class SurveyRow
{
public int QuestionId { get; set; }
public int? ParentQuestionId { get; set; }
public int SurveyId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string HelpInformation { get; set; }
public int RenderOrder { get; set; }
public SurveyRowType RowType { get; set; }
// Collection of the same answer control, 1 or more times
// for each line number
public IList<AnswerControl> AnswerControls { get; set; }
}
public enum SurveyRowType
{
QuestionGroup = 1,
Question = 2,
AnswerRow = 3
}
public class AnswerControl
{
public int Id { get; set; }
public int QuestionId { get; set; }
// a reference to the database record answer id
public int SurveyAnswerId { get; set; }
// control type of checkbox, dropdown, input, dropdown-additional-textbox, checkbox-group
public ControlType ControlType { get; set; }
// used to specify getting particular backing data for dropdown and checkbox-group
public ControlSpecificType ControlSpecificType { get; set; }
public string Description { get; set; }
public string HelpInformation { get; set; }
public int RenderOrder { get; set; }
public bool InLine { get; set; }
public int LineNumber { get; set; }
public AnswerControlValueType Value { get; set; }
}
public class AnswerControlValueType
{
// Default string backing value when possible
public string Value { get; set; }
// AnswerCheckBox
public bool CheckValue { get; set; }
// AnswerCheckBoxListModal
public string ModalName { get; set; }
// AnswerMultiSelectListValue
public int[] ListValues { get; set; }
// making the options list setter public so that this data can be re-attached after model binding
public IEnumerable<SelectListItem> ListOptions { get; set; }
// AnswerImageValue
public HttpPostedFileBase Image { get; set; }
// AnswerSelectListAdditionalValue
public string AdditionalInformation { get; set; }
}
Each SurveyRow
is like a row of a table. Only the SurveyRowType.AnswerRow
actually makes use of the AnswerControls
list.
Example of their ordering when rendered by their type and order number can be seen in this image:
The image only shows a few simple examples, and there can be 1-10 lines per page to a max of 100, but I have also added a bit of explanation of some of the validation rules I would want to apply. There are more but these are just a few examples.
My problem is that I want to support this more complex validation but all the rules and error text are stored in a database, 1. because of user configuration, 2. because of existing localisation of the error text to support several languages.
I am looking for any suggestions that people might have to be able to support this.
I have seen things like Fluent Validation and I haven't delved too deep yet but so far I can't see any examples that would specifically not use Data Annotations on a model.. and also RequiredIf or DisabledIf or EnabledIf style validation rules that apply across a slightly more complex collection of objects.
My question was related to how I can support validating this complex model. I have since looked more at Fluent Validation and that has everything I need to do custom rules for a complex model, i.e. checking values across collections of objects within my model.