1

我有一个我的视图模型都继承自的 BaseViewModel。

public class MagazineViewModel : BaseOutputViewMode
{
    public string TitleOfPublication { get; set; }
}

在我的控制器中,我使用工厂方法根据输入返回正确的视图模型:

// e.g. viewModel contains an instance of MagazineViewModel 
BaseOutputViewModel viewModel = BaseOutputViewModel.GetOutputViewModel(output);

当我使用 TryUpdateModel 尝试绑定到我知道包含“TitleOfPublication”键的 FormCollection 时,它从未在我的视图模型中设置:

if (!TryUpdateModel(viewModel, form))

我认为这与 DefaultModelBinder 使用 BaseOutputViewModel 绑定 FormCollection 键有关 - 它不包含“TitleOfPublication”,派生的 MagazineViewModel 包含。

我正在尝试推出自己的模型绑定器,以覆盖 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 上使用反射器,只有当模型为空时才调用 CreateModel 的“BindComplexModel”:

if (model == null)
{
    model = this.CreateModel(controllerContext, bindingContext, modelType);
}

任何指针都收到了!

干杯

4

1 回答 1

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 在我的派生类型中成功绑定属性!

干杯

于 2010-11-01T12:32:56.723 回答