У меня такая модель:
public class SidebarViewModel
{
public SidebarViewModel()
{
Filters = new List<FilterViewModel>();
}
public List<FilterViewModel> Filters { get; set; }
}
И каждый фильтр выглядит так:
public abstract class FilterViewModel
{
[Required]
public string Value { get; set; }
[HiddenInput(DisplayValue = false)]
public bool Visible { get; set; }
[HiddenInput(DisplayValue = false)]
public abstract string DisplayName { get; }
[HiddenInput(DisplayValue = false)]
public string ModelType { get { return GetType().Name; } }
}
И есть подтипы фильтров, которые выглядят так:
public class TextFilter : FilterViewModel
{
public override string DisplayName
{
get { return "Some Name Here"; }
}
}
Когда публикация происходит, вся модель SidebarViewModel должна быть отправлена контроллеру:
[HttpPost]
public ActionResult Filter(SidebarViewModel sidebar)
{
// Stuff here.
}
Чтобы связать SidebarViewModel, я попытался написать собственный ModelBinder для объектов FilterViewModel:
public class FilterModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var modelName = bindingContext.ModelName;
var filterTypeValue = bindingContext.ValueProvider.GetValue(modelName + ".ModelType");
var filterType = Type.GetType(filterTypeValue.ToString(), true);
var model = Activator.CreateInstance(filterType);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, filterType);
return model;
}
}
И зарегистрировал этот ModelBinder в Global.asax.cs:
ModelBinders.Binders.Add(typeof(FilterViewModel), new FilterModelBinder());
Наконец, вид:
@model SidebarViewModel
@using (Ajax.BeginForm("Filter", SessionVars.ControllerName, new AjaxOptions
{
UpdateTargetId = "tool-wrapper",
LoadingElementId = "loading-image",
HttpMethod = "POST"
}))
{
<fieldset>
@Html.EditorFor(m => m.Filters)
<div class="form-actions">
<button type="submit">Submit Options</button>
</div>
</fieldset>
}
И EditorTemplate:
@model FilterViewModel
<div class="control-group">
@Html.Label(Model.DisplayName, new { @class = "control-label" })
<div class="controls">
@Html.TextBoxFor(m => m.Value)
@Html.HiddenFor(m => m.DisplayName)
@Html.HiddenFor(m => m.ModelType)
@Html.HiddenFor(m => m.Visible)
</div>
</div>
Проблема в том, что при публикации боковой панели FilterModelBinder никогда не вызывается. Нужен ли мне другой связыватель пользовательской модели для SidebarViewModel? Если да, как мне вызвать FilterModelBinder для каждого фильтра в списке боковой панели?