我有以下模型:
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"; }
}
}
当发布时,整个边栏ViewModel应该发布到控制器:
[HttpPost]
public ActionResult Filter(SidebarViewModel sidebar)
{
// Stuff here.
}
为了绑定边栏视图模型,我尝试为FilterViewModel对象编写一个自定义的ModelBinder:
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;
}
}
并在Global.asax.cs:中注册了ModelBinder
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>
}
和编辑器模板:
@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?
啊,我的RuntimeRoute注册出现了问题。里面有一个无效的,删除它解决了我的绑定问题。