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
{ 开发者_StackOverflow
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?
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.
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
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.
精彩评论