【问题标题】:ASP.NET model binding to base typeASP.NET 模型绑定到基类型
【发布时间】:2010-10-31 09:14:58
【问题描述】:

我有一个我的视图模型都继承自的 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 上使用了 Reflector,有一个“BindComplexModel”,仅当模型为 null 时才调用 CreateModel:

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

任何指针都收到了!

干杯

【问题讨论】:

    标签: asp.net-mvc types derived defaultmodelbinder


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

    干杯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-23
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      相关资源
      最近更新 更多