Search code examples
c#asp.net-mvcvalidationmodel-validation

Custom model & client validation in MVC without data annotations


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: enter image description here

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.


Solution

  • 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.