Связыватель настраиваемой модели для списка, вложенного в модель-оболочку

У меня такая модель:

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 для каждого фильтра в списке боковой панели?


person jacobsowles    schedule 26.04.2015    source источник
comment
Вы видели эту ветку = ›stackoverflow.com/questions/9417888/?   -  person CodeNotFound    schedule 26.04.2015
comment
Да, это было так, но у меня все еще та же проблема. Мои классы SidebarViewModel, FilterViewModel и TextFilter отображают сопоставление практически напрямую с классами MyModel, MyBaseClass и MyDerivedClass из принятого ответа в этом потоке. Когда я устанавливаю свою настраиваемую подшивку модели как подшивку по умолчанию, подшивка выполняется, а тип модели - SidebarViewModel, но список FilterViewModels никогда не запускается через настраиваемую подшивку.   -  person jacobsowles    schedule 27.04.2015


Ответы (1)


Ах, это закончилось проблемой с моей регистрацией RuntimeRoute. Там был недействительный, и его удаление устранило мою проблему с привязкой.

person jacobsowles    schedule 26.04.2015