我有一个我的View Models都继承自的BaseViewModel。
public class MagazineViewModel : BaseOutputViewMode
{
public string TitleOfPublication { get; set; }
}
在我的控制器中,我使用工厂方法根据输入提供相应的View Model:
// e.g. viewModel contains an instance of MagazineViewModel
BaseOutputViewModel viewModel = BaseOutputViewModel.GetOutputViewModel(output);
当我使用TryUpdateModel尝试绑定到我知道包含“TitleOfPublication”键的FormCollection时,它从未在我的视图模型中设置:
if (!TryUpdateModel(viewModel, form))
我认为这与使用BaseOutputViewModel绑定FormCollection键的DefaultModelBinder有关 - 它不包含派生的MagazineViewModel的“TitleOfPublication”。
我正在尝试滚动自己的模型绑定器,以覆盖DefaultModelBinder的BindModel行为。它全部连线正确,我可以在TryUpdateModel调用后直接调试它:
public class TestModelBinder : DefaultModelBinder, IFilteredModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Tried the following without success ....
// 1. Quick hardcoded test
// bindingContext.ModelType = typeof(MagazineViewModel);
// 2. Set ModelMetadata, hardcoded test again
// bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(MagazineViewModel));
// 3. Replace the entire context
// ModelBindingContext context2 = new ModelBindingContext();
// context2.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(MagazineViewModel));
// context2.ModelName = bindingContext.ModelName;
// context2.ModelState = bindingContext.ModelState;
// context2.ValueProvider = bindingContext.ValueProvider;
// bindingContext = context2;
}
}
但是我不确定如何使用bindingContext?需要更新什么才能告诉DefaultModelBinder使用派生的View Model属性进行绑定? 或者我完全误解了这个!
我确实尝试重写CreateModel - 就像MvcContrib中的DerivedTypeModelBinder一样,但我认为因为我给了一个模型的实例来使用,所以从不调用CreateModel。在Mvc DLL上使用了Reflector,它是一个“BindComplexModel”,仅当模型为null时才调用CreateModel:
if (model == null)
{
model = this.CreateModel(controllerContext, bindingContext, modelType);
}
任何指针都很受欢迎!
干杯
答案 0 :(得分:1)
好的 - 终于到了最底层! 实际上我的模型绑定器没有任何问题,问题最终导致了几个没有名称/ id的输入标签:
<input id="" name="" type="text">
关键是DefaultModelBinder中的这个测试:
// Simple model = int, string, etc.; determined by calling TypeConverter.CanConvertFrom(typeof(string))
// or by seeing if a value in the request exactly matches the name of the model we're binding.
// Complex type = everything else.
if (!performedFallback) {
ValueProviderResult vpResult =
bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (vpResult != null) {
return BindSimpleModel(controllerContext, bindingContext, vpResult);
}
}
如果没有id / name,表单集合的键为“”,这意味着GetValue正确返回该字段的值,继续绑定为简单模型。
当添加id / name时,表单集合不包含“”的键,(现在我们正在使用TryUpdateModel,这是我的模型的名称)。这意味着DefaultModelBinder正确地将我的模型视为complexm在我的派生类型中成功绑定属性!
干杯