我花了好一天的时间来解决一个密切相关的问题的答案-尽管我不确定这是否是完全相同的问题,但如果有人正在寻找解决同一问题的解决方案,我会在这里发布。
就我而言,我有一个抽象的基本类型,用于多种不同的视图模型类型。 因此,在主视图模型中,我具有抽象基本类型的属性:
class View
{
public AbstractBaseItemView ItemView { get; set; }
}
我有许多AbstractBaseItemView子类型,其中许多定义了自己的专有属性。
我的问题是,模型绑定器不查看附加到View.ItemView的对象的类型,而是仅查看声明的属性类型,即AbstractBaseItemView-并决定仅绑定在抽象类型中定义的属性, 忽略恰好在使用的特定于AbstractBaseItemView具体类型的属性。
解决方法不是很漂亮:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
// ...
public class ModelBinder : DefaultModelBinder
{
// ...
override protected ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.IsAbstract && bindingContext.Model != null)
{
var concreteType = bindingContext.Model.GetType();
if (Nullable.GetUnderlyingType(concreteType) == null)
{
return new AssociatedMetadataTypeTypeDescriptionProvider(concreteType).GetTypeDescriptor(concreteType);
}
}
return base.GetTypeDescriptor(controllerContext, bindingContext);
}
// ...
}
尽管此更改让人感觉很棘手,而且非常“系统”,但它似乎有效-并且据我所知,它不会带来相当大的安全风险,因为它没有绑定到CreateModel()中,因此不允许您 发布任何内容并欺骗模型绑定器以创建任何对象。
它也仅在声明的property-type是抽象类型时才起作用,例如 抽象类或接口。
与此相关的是,在我看来,我在这里看到的覆盖CreateModel()的其他实现可能仅在发布全新的对象时才起作用-并且在声明的属性时也会遇到我遇到的相同问题 -type是抽象类型。 因此,您很可能将无法在现有模型对象上编辑具体类型的特定属性,而只能创建新的属性。
因此,换句话说,您可能需要将此替代方法集成到活页夹中,以便还能够正确地编辑在绑定之前添加到视图模型中的对象...就我个人而言,我认为这是一种更安全的方法,因为 我控制要添加的具体类型-因此,控制器/操作可以通过简单地用空实例填充属性来间接指定可能绑定的具体类型。
我希望这对其他人有帮助...