使用抽象类的 Asp.Net MVC 2 DefaultModelBinder 错误

发布于 2024-08-24 13:03:31 字数 1787 浏览 15 评论 0原文

我有一个使用抽象类的简单 Poco-Model,它似乎不适用于 Asp.net MVC 2 的默认 ModelBinder。 一个项目在一个集合中有多个对象,所有对象都使用相同的抽象基类。

模型:

    public partial class Item
    {  
        public virtual ICollection<Core.Object> Objects
        {
            get
            {
                return _objects;
            }
            set
            {                
                    if (value != _objects)
                    {
                        _objects = value;
                    }
            }
        }
        private ICollection<Core.Object> _objects;
    }   


 public abstract partial class Object
    {

        public virtual Item Item
        {
            get
            {
                return _item;
            }
            set
            {
                if (!Object.ReferenceEquals(_item, value))
                {
                    _item = value;
                }
            }
        }
        private Item _item;       

    }

    public partial class TextObject : Object
    {
        public virtual string Text { get; set; }
    }

实例:

var NewItem = new Item();                    
var TextObject1 = new TextObject
{
   Text = "Text Object Text",
   Item = NewItem
};                      
List<Core.Object> objects = new List<Core.Object>(){TextObject1};            
NewItem.Objects = objects;

使用对象集合中带有一个 TextObject 的该项目的默认 Html.EditorForModel() 帮助程序,我得到一个如下所示的 html 输入字段:

<input class="text-box single-line" id="Objects_0__Text" name="Objects[0].Text" type="text" value="Text Object Text" />

当回发到控制器时,我得到一条“无法创建抽象类”错误消息来自默认 ModelBinder。显然,绑定器尝试实例化该抽象基类。但我不知道为什么,因为集合中只有一个继承的 TextObject 类型的对象。 有没有其他方法可以在不编写自定义 Modelbinder 的情况下使其正常工作?

I have a simple Poco-Model using abstract classes, and it seems not to work with the Default ModelBinder of Asp.net MVC 2.
One Item has several Objects in a collection, all using the same abstract base class.

Model:

    public partial class Item
    {  
        public virtual ICollection<Core.Object> Objects
        {
            get
            {
                return _objects;
            }
            set
            {                
                    if (value != _objects)
                    {
                        _objects = value;
                    }
            }
        }
        private ICollection<Core.Object> _objects;
    }   


 public abstract partial class Object
    {

        public virtual Item Item
        {
            get
            {
                return _item;
            }
            set
            {
                if (!Object.ReferenceEquals(_item, value))
                {
                    _item = value;
                }
            }
        }
        private Item _item;       

    }

    public partial class TextObject : Object
    {
        public virtual string Text { get; set; }
    }

Instance:

var NewItem = new Item();                    
var TextObject1 = new TextObject
{
   Text = "Text Object Text",
   Item = NewItem
};                      
List<Core.Object> objects = new List<Core.Object>(){TextObject1};            
NewItem.Objects = objects;

Using the Default Html.EditorForModel() Helper for that item with one TextObject in the Objects collection I get a html input-field like that:

<input class="text-box single-line" id="Objects_0__Text" name="Objects[0].Text" type="text" value="Text Object Text" />

When posting back to the Controller I get an "Cannot create an abstract class" Errormessage from the Default ModelBinder. Obviously the binder tries to instantiate that abstract base class. But I don't know why, since there are is only an object of the inherited TextObject type in the collection.
Is there any other way to get this working without writing a custom Modelbinder?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉南桥 2024-08-31 13:03:31

您将必须使用自定义模型绑定器或使用视图模型。模型绑定器只知道您用作操作参数的类型(包含抽象类)。然后它尝试将请求中的值映射到该模型。绑定器不可能知道它应该使用其他实现以及可能是什么实现。

我的建议是创建更简单的视图模型并使用 automapper 映射它们。

You will have to use a custom model binder or use viewmodels. The model binder only knows about the type that you use as a parameter to your action (contains the abstract class). Then it tries to map values from the request to that model. There is no way the binder could know that it should use some other implementation and what implementation that might be.

My advice is to create viewmodels that are simpler and map them using automapper.

-残月青衣踏尘吟 2024-08-31 13:03:31

查看 MvcContrib 中的 DerivedTypeModelBinder。 TypeStamping 将元数据注入视图渲染中,为衍生类型模型绑定器提供正确调用要实例化的对象所需的信息。更长的讨论,链接到此

用于派生对象列表的 MVC2 Modelbinder

Check out the DerivedTypeModelBinder in MvcContrib. The TypeStamping injects metadata into the view rendering, giving the derivedtypemodelbinder the information needed to make the proper call on what object to instantiate. A longer discussion with links to this

MVC2 Modelbinder for List of derived objects

北斗星光 2024-08-31 13:03:31

我认为您必须在 Item 类中将 Objects 集合指定为 ICollection
否则,默认模型绑定器将不可能意识到它应该创建什么对象。
如果您决定创建自定义模型绑定程序,则需要在表单中为每个对象添加一个指示其类型的字段。
问候。

I think you´ll have to specify in the Item class the Objects collection as an ICollection<TextObject>.
Otherwise, it would be impossible for the default model binder to realize what object it should create.
If you decide to create a custom model binder, you´ll need to add in the form, for every Object, a field indicating its type.
Regards.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文