Добрый день!
На MVC странице часть контролов создаются динамически (например из БД). Все такие контролы наследуются от абстрактнго базового класса ControlViewModel. С отображением контролов на странице проблем нет. Хотелось бы обрабатывать в контроллере по кнопке данные, введенные пользователем в эти контролы. Проблема в том, что выбрасывается исключение System.MissingMethodException: Cannot create an abstract class.
Ошибка, как я понимаю, в переопределенном методе CreateModel в классе ControlModelBinder (наследуется от DefaultModelBinder). Что вообще надо там писать, чтобы получть текущюю модель?
Делаю так:
1. Форма
@using (Html.BeginForm())
{
for (int i = 0; i < Model.Controls.Length; i++)
{
if (Model.Controls[i].Visible)
{
<div>
@Html.HiddenFor(x => x.Controls[i].Type)
@Html.HiddenFor(x => x.Controls[i].Name)
@Html.EditorFor(x => x.Controls[i])
</div>
}
}
@Html.Button(settings =>
{
settings.Name = "ButtonSave";
settings.UseSubmitBehavior = true;
settings.RouteValues = new { Controller = "Contr", Action = "Save" };
}).GetHtml()
}
2. Метод контроллера указанием на свой ControlModelBinder
[HttpPost]
public ActionResult Save([ModelBinder(typeof(ControlModelBinder))] MyModel myModel)
{
// В это место вообще не прихожу из-за ошибки System.MissingMethodException: Cannot create an abstract class.
}
3. Модель:
public class MyModel : ModelBase
{
public ControlViewModel[] Controls { get; set; } // Массив динамически создаваемых контролов
}
4.Классы для контролов:
public abstract class ControlViewModel
{
public abstract string Type { get; }
public bool Visible { get; set; }
public string Name { get; set; }
}
public class TextBoxViewModel : ControlViewModel
{
public override string Type
{
get { return "textbox"; }
}
public string Value { get; set; }
}
5. Свой ControlModelBinder:
public class ControlModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
object model = null;
// что тут пписать - не понятно.
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
return model;
}
}