Question

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.

Was it helpful?

Solution 2

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.

OTHER TIPS

I worked with MVC patterns in 2001 with servlets, and again in 2006, with a custom MVC framework implemented on top of ASP.NET, and looking at what people are doing nowadays makes me believe that most did not even care about looking at what MVC stands for, only that explain the models nonsense. A lot of developers working with ASP.net MVC, tend to bind the data that is coming from the client to models, but that is such a poor design. Models contain the data that should be forwarded to the template manager which is in most cases the Razor engine.

http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

So my advice is: don't link the data that you get from the client into the models.

  • Get the data from the client, do a search on the Request object if it needs to
  • Validate the data (fluentvalidation)
  • apply the business rules
  • create the models
  • forward the models to the template engine

Also stopping using those crazy useless annotations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top