0

I am using MVC3 and am trying to leverage the Child Action feature @Html.Action() so I have a View with the following


    @foreach (var item in Model.Items){
        @Html.Action("GetFormItemView", "Question", item});
    }

This calls the following method


    [ChildActionOnly]
    public ActionResult GetFormItemView(FormItem formItem)
    {
        if (formItem is FormSection)
        {
            return GetSectionView(formItem as FormSection);
        }
        else if (formItem is QuestionItem)
        {
            return GetTypedQuestionView(formItem as QuestionItem);
        }
        else
        {
            throw new NotImplementedException();
        }
    }

At this point the Model Bind bombs telling me it can't create an abstract class....

Server Error in '/' Application. Cannot create an abstract class. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: Cannot create an abstract class.

How do I get the model binder to get out of my way - I have provided the Action with the necessary model...?

Jon Hoguet
  • 93
  • 1
  • 7

2 Answers2

0

Stab in the dark, but I think you need:

@foreach (var item in Model.Items){
   @Html.Action("GetFormItemView", "Question", new {formItem = item});
}
Daryl Teo
  • 5,394
  • 1
  • 31
  • 37
0

The problem is that the model binder does not know how to recreate your concrete class based only on the parameters. Look at the view yourself, and you will see that there is no way the Model Binder could know to create the correct class.

The model binder should be smart enough to walk the descendants of your base class and instantiate the right one, but unfortunately, it's not. There are probably edge cases that make this unreliable.

The easiest solution is to create seperate actions for each concrete model type. More complex solutions exist, you can check this question for examples.

Community
  • 1
  • 1
Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • Thanks for the quick response - I had read the link you posted. I understand that the model binder doesn't know which concrete class to use. BUT - I have given it the concrete class from the parent view. I essentially don't need the model binder to get involved at all, simply pass the argument along to the Action. Any ideas? – Jon Hoguet Sep 19 '11 at 17:01
  • In that case, instead of using the container class, just accept all parameters individually. That works for me. – Daryl Teo Sep 19 '11 at 17:08
  • FormItem is a base class not so much a container class - deconstructing it to individual parameters would make for a long method signature and I would have to workaround the polymorphism - that's not an option at this time. Please let me know if I have misunderstood your intent... – Jon Hoguet Sep 19 '11 at 17:20
  • 1
    @Jon Hoguet - Then you should use a partial view. `Html.Action` goes through the binder process. No way around that, Partial Views do not. – Erik Funkenbusch Sep 19 '11 at 17:21