Question

I have written a custom model binder for List in my MVC project however I am now stuck in how to get this binder to validate against my DataAnnotations validation attributes.

I have found some posts on the interwebs that talk about similar scenarios, but I haven't been able to find anything that works for my particular scenario.

Model Binder Code:

    public class QuestionModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        List<QuestionEditModel> res = new List<QuestionEditModel>();
        var form = controllerContext.HttpContext.Request.Form;
        int i = 0;
        while (!string.IsNullOrEmpty(form["Questions[" + i + "].QuestionID"]))
        {
            var p = new QuestionEditModel();
            p.QuestionID = form["Questions[" + i + "].QuestionID"];
            p.Answer = form["Questions[" + i + "].Answer"];
            p.AnswerRequired = (form["Questions[" + i + "].AnswerRequired"] == "True") ? true : false;
            p.completedBy = form["Questions[" + i + "].completedBy"];
            p.completedOn=NullableParser.ParseNullableDateTime(form["Questions[" + i + "].CompletedOn"]);
            p.DefaultText = form["Questions[" + i + "].DefaultText"];
            p.EntryType = form["Questions[" + i + "].EntryType"];
            p.HelpText = form["Questions[" + i + "].HelpText"];
            p.OptionRequired = (form["Questions[" + i + "].OptionRequired"] == "True") ? true : false;
            p.OptionValue = NullableParser.ParseNullableInt(form["Questions[" + i + "].OptionValue"]);
            p.QuestionName = form["Questions[" + i + "].QuestionName"];
            p.QuestionText = form["Questions[" + i + "].QuestionText"];
            res.Add(p);
            i++;
        }

        return res;
    }

    private bool HasGenericTypeBase(System.Type type, System.Type genericType)
    {
    while (type != typeof(object))
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType) return true;
        type = type.BaseType;
    }

    return false;        
    }

}

My Model MetaData:

    [MetadataType(typeof(QuestionEditModelMetaData))]
public partial class QuestionEditModel { }


public class QuestionEditModelMetaData
{
    [Required]
    public string QuestionID { get; set; }
    [Required]
    public string QuestionName { get; set; }
    [Required]
    public string QuestionText { get; set; }
    [Required]
    public string DefaultText { get; set; }
    [Required]
    public string EntryType { get; set; }
    [Required]
    public string HelpText { get; set; }

    public Boolean AnswerRequired { get; set; }
    public Boolean OptionRequired { get; set; }

    //[RequiredIfTrue("AnswerRequired")]
    [Required]
    public string Answer { get; set; }

    [RequiredIfTrue("OptionRequired")]
    public int? OptionValue { get; set; }

    public string completedBy { get; set; }
    public DateTime? completedOn { get; set; }

    public List<Option> options { get; set; }

}

The RequiredIfTrue attribute is from the MVC Foolproof Validation library. Apparently it isn't quite foolproof enough!

Was it helpful?

Solution

The solution from here works.

Custom model binding, model state, and data annotations

The CreateModel option makes life really easy.

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