JSON
JSON

Reputation: 1623

Why am I getting an invalid JSON after serialization using EF?

I have the following two models, PatientRegistry and PartnerRegistry. The relationship between those models is one to many.

I am trying to read the record and its related one but I am getting a broken JSON at PartnerRegistry. The only way I got it to work is by using Automapper, but why is this happening? Do I need to call the context for the second model? My understanding is that EF will automatically do that once a relationship is established.

EDIT

I removed some prop just to shorten the list

[Table("PatientsRegistry")]
    public class PatientRegistry
    {   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Display(Name = "Record Id")]
        public long RecordId { get; set; }
        [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Display(Name = "Patient File Number")]
        public long PatientFileId { get; set; }
        [Required, StringLength(50)]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
        [Required, StringLength(50)]
        public string SecondName { get; set; }
        [Required, StringLength(50)]        
        public string LastName { get; set; }
        public int GenderId { get; set; }
        public Gender Gender { get; set; }
        public DateTime DateCreated { get; set; } = DateTime.UtcNow;
        [Timestamp]
        public byte[] RowVersion { get; set; }
        public ICollection<PartnerRegistry> Partners { get; set; }
        public PatientRegistry()
        {
            Partners = new Collection<PartnerRegistry>();
        }

    }
public class PartnerRegistry
    {   
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long RecordId { get; set; }
        public long PatientFileId { get; set; }
        public long PartnerFileId { get; set; }
        public PatientRegistry PatientsRegistry { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime? EndDate { get; set; }

    }

and my controller is

 [HttpGet("{id}")]
    public async Task<IActionResult> getAll(long Ids)
    {
          var patient = await context.PatientsRegistry
        .Include(pt => pt.Gender)
        .Include(pt => pt.Partners)
        .SingleOrDefaultAsync(pt => pt.PatientFileId == Ids);

        return Ok(patient);
    }

The output is

{
    "recordId": 1,
    "patientFileId": 1111,
    "firstName": "John",
    "secondName": "M",
    "lastName": "Doe",
    "genderId": 1,
    "gender": {
        "id": 1,
        "name": "Male"
    },
    "dateCreated": "2017-11-25T08:40:07.75444",
    "rowVersion": "AAAAAAAAB9E=",
    "partners": [{
                "recordId": 1,
                "patientFileId": 1111,
                "partnerFileId": 2222

You can notice that there are missing properties that were not mapped by ef! The properties that were not populated are, StartDate and EndDate

Upvotes: 2

Views: 109

Answers (3)

JSON
JSON

Reputation: 1623

Update:

also I found that this problem can be resolved globally via this configuration,

    services.AddMvc()
    .AddJsonOptions(options => 
     options.SerializerSettings.ReferenceLoopHandling =
     Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Ref

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273701

A quick fix:

public class PartnerRegistry
{   
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long RecordId { get; set; }
    public long PatientFileId { get; set; }
    public long PartnerFileId { get; set; }

    [JsonIgnore]  // add this
    public PatientRegistry PatientsRegistry { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
}

Edit, a small mcve:

class Patient
{
    public string  Name { get; set; }
    public ICollection<Partner> Partners { get; set; }
}

class Partner
{
    public string Name { get; set; }
    //[JsonIgnore]
    public Patient Patient { get; set; }
}

with thes classes and Partners filled,

string text = JsonConvert.SerializeObject(patient1);

will throw

Newtonsoft.Json.JsonSerializationException: 'Self referencing loop detected for property 'Patient' with type 'App1.Patient'. Path 'Partners[0]'.'

Upvotes: 1

Johan van Tonder
Johan van Tonder

Reputation: 345

Put [ScriptIgnore] attribute on the PatientRegistry Property of the PartnerRegistry class. This attribute is available from System.Web.Script.Serialization. There could be a circular references halting the serialization/deserialization.

Upvotes: 1

Related Questions