How to model bind a class that implements an interface?
asp.net-mvc-3
Solution
what am i doing wrong?
You cannot expect the model binder to know that when it encounters the `IQuestionAnswer` interface on your `SurveyAnswer` view model it should use the `QuestionAnswer` type. It's nice that you have declared this implementation of the interface but the model binder has no clue about it.
So you will have to write a custom model binder for the `IQuestionAnswer` interface (same for the `IHiddenAnswer` interface) and indicate which implementation do you want to be used:
public class QuestionAnswerModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var type = typeof(QuestionAnswer);
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
}
}
which will be registered in your `Application_Start`:
ModelBinders.Binders.Add(typeof(IQuestionAnswer), new QuestionAnswerModelBinder());
Problem
The model binding worked fine until i implemented interfaces on top of the following classes: ``` public class QuestionAnswer : IQuestionAnswer { public Int32 Row_ID { get; set; } public Int32 Column_ID { get; set; } public String Value { get; set; } } public class HiddenAnswer : IHiddenAnswer { public Int32 Hidden_Field_ID { get; set; } public String Hidden_Field_Value { get; set; } } public class SurveyAnswer : ISurveyAnswer { public string SessionID { get; set; } public List<IQuestionAnswer> QuestionAnswerList { get; set; } public List<IHiddenAnswer> HiddenAnswerList { get; set; } public SurveyAnswer() { QuestionAnswerList = new List<IQuestionAnswer>(); HiddenAnswerList = new List<IHiddenAnswer>(); } } ``` Now that the interfaces are there, i get a `500 (Internal Server Error)` The javascript that i use to model bind is the following: ``` $('#submitbutton').click(function () { var answers = new Array(); var hiddenfields = new Array(); var formname = "#" + $("#formname").val(); $(':input', formname).each(function () { if ($(this).is(":text") || $(this).is(":radio") || $(this).is(":checkbox")) { var answerObject = { Column_ID: $(this).attr('data-column_id'), Row_ID: $(this).attr('data-row_id'), Value: $(this).attr('data-theValue') }; answers.push(answerObject); } else if($(this).is(":hidden")) { var hiddenObject = { Hidden_Field_ID: $(this).attr('data-hidden_field_id'), Hidden_Field_Value: $(this).attr('data-hidden_field_value') } hiddenfields.push(hiddenObject); } }); $('textarea', formname).each(function () { var answerObject = { Column_ID: $(this).attr('data-column_id'), Row_ID: $(this).attr('data-row_id'), Value: $(this).val(), }; answers.push(answerObject); }); var allAnswers = { SessionID: 0, QuestionAnswerList: answers, HiddenAnswerList: hiddenfields } postForm(allAnswers); }); ``` The Controller Action looks like this: ``` [AcceptVerbs(HttpVerbs.Post)] public ActionResult SubmitSurvey(SurveyAnswer answers) { // Dette tillader CORS Response.AppendHeader("Access-Control-Allow-Origin", "*"); bc.SaveSurvey(answers); return null; } ``` what am i doing wrong?