首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVC模型绑定-抽象集合属性

MVC模型绑定-抽象集合属性
EN

Stack Overflow用户
提问于 2013-07-22 06:24:44
回答 3查看 3.3K关注 0票数 3

不重复,请参阅附加说明

我想像下面这样绑定一个模型设置

代码语言:javascript
复制
public class Shop{
    public string Name {get;set;}
    public ICollection<Product> Products {get;set;} //Product is abstract
}

public abstract class Product{
    public string Name {get;set;}
}

public class ProductA : Product{
    public string foo {get;set;}
}

public class ProductB :Product{
    public string bar {get;set;}
}

像这样的控制器

代码语言:javascript
复制
public ActionResult(){
    Shop model = ShopFactory.GetShop();
    return View(model);
}

[HttpPost]
public ActionResult(Shop model){
    //....
}

我使用BeginCollectionItem绑定集合,但是当POSTing表单不能创建抽象类(即Shop.Products中的对象)时,出现了一个问题

我看过用子类DefaultModelBinder来覆盖CreateModel,但是参数modeltype = Product从来没有调用CreateModel,只有modeltype = Shop

如何创建将具有抽象集合的对象绑定为属性的ModelBinder?

Clarification

这个问题不是重复的,因为我们不是在处理抽象模型,而是处理一个具有抽象对象集合的模型,这在模型绑定系统中经历了一个单独的过程。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-24 02:11:54

回答:

我遇到的问题是,我正在为Shop创建一个Shop,而不是Products

很简单。

更新

既然这被否决了,我想我应该澄清一下。

我试图对Shop类进行模态绑定,因为这是我发送到视图的类。在我的头脑中,这是有意义的,因为那是我所依赖的模型。问题是,DefaultModelBinder中的一个方法称为CreateModel,当它在IEnumerable中遇到任何复杂对象时。所以解决方案是子类DefaultModelBinder

代码语言:javascript
复制
public class ProductModelBinder : DefaultModelBinder{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        if (modelType.Equals(typeof(Product)))
        {
            //For now only support Product1's
            // Todo: Add support for different types
            Type instantiationType = typeof(Product1);
            var obj = Activator.CreateInstance(instantiationType);
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
            bindingContext.ModelMetadata.Model = obj;
            return obj;
        }

        return base.CreateModel(controllerContext, bindingContext, modelType);
    }

并将所述子类注册为绑定程序:

代码语言:javascript
复制
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(FormItem), new Forms.Mvc.FormItemModelBinder()));
票数 3
EN

Stack Overflow用户

发布于 2014-11-28 11:52:36

我只想澄清一下,对于我这样的人来说,他们无意中发现了这一页,寻找一个解决方案:

MVC 3模型绑定子类型(抽象类或接口)正是你要找的东西。您不需要因为BeginCollectionItem而做任何特别的事情。

只需为有一个集合的抽象类编写一个模型绑定,并用以下方式装饰抽象类:

代码语言:javascript
复制
[ModelBinder(typeof(MyModelBinder))]
public abstract class MyClass { ...

然后在您的ModelBinder中,使用如下内容:

代码语言:javascript
复制
string typeName = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".type").AttemptedValue;
Type instantiationType = Type.GetType(typeName);

要从EditorTemplate的隐藏字段获取类型:

代码语言:javascript
复制
    @Html.HiddenFor(m => type)

最后,如果仍然无法获得具体类型的属性,请再次检查它们实际上是属性,而不是字段!

票数 3
EN

Stack Overflow用户

发布于 2013-07-22 06:31:59

我认为您应该编写自定义模型binder.please --参见如何将抽象类或接口集合绑定到模型- ASP.NET MVCMVC 3模型绑定子类型(抽象类或接口)

代码语言:javascript
复制
public class MyModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        /// MyBaseClass and MyDerievedClass are hardcoded.
        /// We can use reflection to read the assembly and get concrete types of any base type
        if (modelType.Equals(typeof(MyBaseClass)))
        {
            Type instantiationType = typeof(MyDerievedClass);                
            var obj=Activator.CreateInstance(instantiationType);
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
            bindingContext.ModelMetadata.Model = obj;
            return obj;
        }
        return base.CreateModel(controllerContext, bindingContext, modelType);
    }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17781153

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档