I am building a ASP.NET webapplication and I am also working with Entity Framework Code First. In this case I am using two entities (Customer and Contact) which have a One-to-Many relation with eachother (one Customer can have multiple Contacts). While getting the data from the database, everything goes fine. I also use Viewmodels, so next to my data entities, I also have two models called CustomerModel and ContactModel.
Below here I will show my entities and my viewmodels:
Customer-entity
[Table("Customer")]
public class Customer
{
[Key()]
public Guid Id { get; set; }
//other non-relevant properties
public virtual List<Contact> Contacts { get; set; }
}
Contact-entity
[Table("Contact")]
public class Contact
{
[Key()]
public Guid Id { get; set; }
//non-relevant properties
[ForeignKey("Customer")]
public Guid CustomerId { get; set; }
[Required]
public virtual Customer Customer { get; set; }
}
CustomerModel
[Serializable]
public class CustomerModel
{
public Guid Id { get; set; }
//non-relevant properties
[ScriptIgnore(ApplyToOverrides = true)]
public virtual List<ContactModel> Contacts { get; set; }
}
ContactModel
[Serializable]
public class ContactModel
{
public Guid Id { get; set; }
//non-relevant properties
public Guid CustomerId { get; set; }
[ScriptIgnore(ApplyToOverrides = true)]
public virtual CustomerModel Customer { get; set; }
}
When I run my application and the code as well, it all works fine in the backend until it needs to serialize it to JSON in my HomeController.
public ActionResult GetCustomerById(Guid id)
{
CustomerModel customer = new CustomerManager().GetById(id);
string output = serializer.Serialize(customer);
return Content(output);
}
Even the CustomerModel
object gets the 2 contacts, but at my Serialize(customer)
method, it doesn't parse it to JSON
. So actually, when I debug it and look at my output, I see every property but not the nested ContactModels.
In my case the string output
doesn't contain the two Contacts
. How do I solve this? I have checked some 'similar' questions on Stackoverflow as well but with no result.
Okay, i see you are missing a concept DTO and circular refferencing, in simplicity you must make a model of the content you want to deliver. What's biting you is layers/refferences, so I did away with all the loopyness in our models.
Think of a -> b -> a that whould result in a json looking something like this
{ a:b{a:b{a:b{a:b{a:b{a:b{a:b{a:b{a:b{a:b{a}}}}}}}}}} //Into infinity and beyond }
This is in essence what you want.
public JsonResult GetCustomerById(Guid id)
{
CustomerModel customer = new CustomerManager().GetById(id);
CustomerResultModel output = new CustomerResultModel(){
id = customer.Id,
Contacts = GetContacts(customer.Contacts)
};
return Json(output, JsonRequestBehavior.AllowGet);
//If you only POST then remove the AllowGet (the action name says Get so I'm assuming
}
private IEnumerable<ContactResultModel> GetContacts(Contacts){
foreach(var a in Contacts){
//When you use the yield keyword in a statement, you indicate that the method, operator, or get accessor in which it appears is an iterator.
yield return new ContactResultModel(){
Id = a.Id,
CustomerId = a.CustomerId
};
}
}
Models
class CustomerResultModel{
public Guid id {get;set;}
public IEnumerable<ContactResultModel> Contacts {get;set;}
}
class ContactResultModel{
public Guid id {get;set;}
public Guid CustomerId {get;set;}
}