I'm building a ASP.NET 5 MVC application, using EF 7. I've got three models: The Book class:
public class Book : IBook<MangaChapter>, IHasThumbnail, IBugChecker
{
public Book()
{
Chapters = new List<MangaChapter>();
}
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
public string ThumbnailPath { get; set; }
public virtual IList<Chapter> Chapters { get; set; }
}
The chapter class:
public class MangaChapter : IChapter<MangaBook>, IHasThumbnail
{
public MangaChapter()
{
PagesPath = new List<Path>();
}
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
public string ThumbnailPath { get; set; }
public IList<Path> PagesPath { get; set; }
public int BookID { get; set; }
public MangaBook Book { get; set; }
}
}
and the path class, that I introduced just to store a list in EF
public class Path
{
public Path(string s) { P = s; }
public int ID { get; set; }
public string P { get; set; }
public int MangaChapterID { get; set; }
public MangaChapter MangaChapter { get; set; }
public static implicit operator Path(string s)
{
return new Path(s);
}
public static implicit operator string(Path s)
{ return s.P; }
}
the Problem is when I try to access the database using myDbContext, in this way:
var list = _db.Paths.ToList();
I get a Exception: ArgumentNullException: Value cannot be null. Parameter name: constructor. I've tried to access it in different ways, but always ended up with that exception.
P.S. the source code for the application is entirely on GitHub
You need a default constructor on the Path
object:
public Path()
{
}
Entity Framework (much like all the JSON Serializers, XML Serializers, and other serailizers I can think of) requires a default constructor on all objects in order to properly serialize/save and deserailize/load it.
This question answers it pretty well:
No parameterless constructor defined for type of 'System.String' during JSON deserialization
Basically, the Serailizer/Deserailizer needs to create an empty object to assign values to it. It is not capable of making a complex decision of deciding what constructor to use. Yes, an argument could be made that it could infer what properties go into the constructor by the names, but in your situation it cannot even do that (which it wouldn't even try to, but that's beyond my point). The parameter in your constructor would is called s
, but you have no property with which to match up s
. (Again, this is not anything it would try, but if it could it would fail.)
Basically, if you plan on doing any serialization/deserialization/database saving/database loading of the type, you need to implement a default constructor, even if all it does is create a completely emptied object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With