I’m having issues getting my controller to recognize the subclass model on a postback.
I’m creating a dynamic web form with the field meta data stored in the db. For my ViewModels, I have a two parent types
public class Form
{
public List<Question> Questions { get; set; }
}
public class Question
{
public string QuestionText { get; set; }
}
and subclass of Question
public class TextBoxQuestion : Question
{
public string TextAnswer { get; set; }
public int TextBoxWidth { get; set; }
}
I also have a view that takes a Form type as the Model and two display templates, one for Question and one form TextBoxQuestion.
//Views/Form/index.cshtml
@model Form
@Html.DisplayFor(m => m.Questions)
–
//Views/Shared/DisplayTemplates/Question.cshtml
@model Question
@if(Model is TextBoxQuestion)
{
@Html.DisplayForModel("TextBoxQuestion")
}
–
//Views/Shared/DisplayTemplates/TextBoxQuestion.cshtml
@model TextBoxQuestion
<div>
@Model.QuestionText
@Html.TextBoxFor(m => m.TextAnswer)
</div>
When the page loads, my controller creates an instance of TextBoxQuestion, adds it to the Question collection and passes the Form object to the view. Everything works find and the textbox appears on the page.
But when I postback to the controller, the code doesn’t recognize the question as a TextBoxQuestion. It only sees it as the parent type Question.
[HttpPost]
public ActionResult Index(Form f)
{
foreach (var q in f.Questions)
{
if (q is TextBoxQuestion)
{
//code never gets here
}
else if (q is Form)
{
//gets here instead
}
}
}
Is there something I’m missing?
The model binder will create an instance of the type the method is expecting. If you want to use subclasses and display templates this way you will need to write your own model binder.
I would suggest to check for existence of one or several attributes to determine whether a
TextBoxQuestionorQuestionis being posted.Modelbinder:
Then hook it up in Global.asax.cs: