5

I'm building an SPA on Angular2 (front-end) and back-end web API 2 with OWIN and Identity for authentication and Ninject as a container for DI.

I want to return a list of Managers as json response. And also its related ContactDetail data. They are related as one-to-one in my database. But I'm getting a 500 error as response. Why am I getting this error?

Microsoft SQL Server Diagram

Manager class

   public partial class Manager
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ContactDetail ContactDetail { get; set; }
}

ContactDetail class

    public partial class ContactDetail
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public string LastName { get; set; }

    public virtual Manager Manager { get; set; }
}

Context

 public partial class LightCRMEntities : DbContext
{
    public LightCRMEntities()
        : base("name=LightCRMEntities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<ContactDetail> ContactDetails { get; set; }
    public virtual DbSet<Manager> Managers { get; set; }
}

API controller

[Authorize(Roles = "Admin, Moderators")]

public class ManagerAPIController : ApiController
{
    private IManagerRepository _iManagerRepository;

    public ManagerAPIController(IManagerRepository iManagerRepository)
    {
        _iManagerRepository = iManagerRepository;
    }


    [HttpGet]
    [Route("api/AllManagers")]
    public IHttpActionResult GetAllManagers()
    {
        var managers = _iManagerRepository.Managers;
        return Json(managers);
    }
}

Repository:

 public class EFManagerRepository : IManagerRepository
{
    public IEnumerable<Manager> Managers
    {
        get
        {
            using (LightCRMEntities context = new LightCRMEntities())
            {
                return context.Managers.ToList();

            }
        }
    }

}

Error

  • ContactDetail '((System.Data.Entity.DynamicProxies.Manager_63305B0F1D8DAA0805603D889C6E3A5114E3050AEE610FE775000D2270697C1F)(new System.Collections.Generic.Mscorlib_CollectionDebugView(managers).Items[0])).ContactDetail' threw an exception of type 'System.ObjectDisposedException' LightCRM.ContactDetail {System.ObjectDisposedException}

Response:

I'm receiving 500 (Internal server error)

ExceptionMessage : "Error getting value from 'ContactDetail' on 'System.Data.Entity.DynamicProxies.Manager_63305B0F1D8DAA0805603D889C6E3A5114E3050AEE610FE775000D2270697C1F'." ExceptionType : "Newtonsoft.Json.JsonSerializationException"

Screenshot of a breakpoint: Though the error does not appear on this point - I can see that one of the related entities ContactDetail - has some problem to be loaded

breakpoint

I hardly understand the meaning of: Configuration.ProxyCreationEnabled = false; but if I add it to the constructor of the Context:

 public partial class LightCRMEntities : DbContext
{
    public LightCRMEntities()
        : base("name=LightCRMEntities")
    {
        Configuration.ProxyCreationEnabled = false;
    }
 // other code
}

Then I get 200 ok and a json object in console: json response

but it dosn't load the related object - it has a NULL value - ContactDetail : null

SQL profiler screenshot for this request:

SQL profiler

Screenshot of data in the database:

data in database

Dmitriy Klyushin
  • 437
  • 1
  • 4
  • 17
  • Need more information. Is this a web back-end that is serving json to a front-end? Can you add a break-point to see what line is generating the error? Also, have you confirmed that the database is receiving and responding to requests (SQL Profiler can help with this). – J Weezy Jul 22 '18 at 00:24
  • I'm building an SPA on Angular2 (front-end) and back-end web API 2 + Microsoft SQL server 2016. I've added some additional info to the original post. And and a screenshot of the breakpoint as well . But I should say it doesn't break at that point. I just stop it at that point and see that the variable I want to return has a related entity that has failed to load. It's the first time I hear of the SQL Profiler - I'll try to find out about it and use it to see if DB receiving/responding. – Dmitriy Klyushin Jul 22 '18 at 00:39
  • SQL Profiler comes installed with SQL Server. Its easy, open the application, start a new trace (in the file menu), select your server instance then click run. The trace is now watching all requests and responses to the server. So, for debugging purposes, it helps to shut down all processes that are hitting the server because your web app's calls may get buried. Anyways, now that the trace is running, run your web app and see if the server both receives and returns a response. – J Weezy Jul 22 '18 at 00:43
  • 1
    It may be because it cannot be serialized (I am just guessing). Remove the navigation property from one of the classes so there is no circularity and retry. – CodingYoshi Jul 22 '18 at 00:45
  • I also used Configuration.ProxyCreationEnabled = false; and then I receive a 200 ok and a json object but then related entity (ContactDetail) is null. Added the screen to the original post. – Dmitriy Klyushin Jul 22 '18 at 00:53
  • 1
    Try disabling lazy loading and eager load your children: `return context.Managers.Include(m => m.ContactDetail).ToList();` – DavidG Jul 22 '18 at 01:01
  • @DmitriyKlyushin If Manager data is returning 200 in the front-end, then I am satisfied that the server is returning data. There must be a problem with either the data in the table or the way the entities are mapped/handled on the back-end. Just covering my bases here, do you have records loaded in the database for Contacts that map to a manager? Can you post a screenshot of the data that is loaded for contacts and managers in the database? – J Weezy Jul 22 '18 at 01:09
  • @JWeezy I added a screen to the original post and also here's a [screenshot](https://vgy.me/0lO68A.png) here in the comment. There are only three lines of data in both tables. – Dmitriy Klyushin Jul 22 '18 at 01:24
  • @DavidG I followed your advice and added `Configuration.LazyLoadingEnabled = false;` to Context in the constructor + I used include - `return context.Managers.Include("ContactDetail").ToList();` - I had to use the name of the entity as a string parameter - I don't know why but there was no variant to use lambda only string param. Still at the breakpoint now I see that the related object IS loaded but It seems to be looped [screenshot](https://vgy.me/GgaI2E.png) And still the error code is 500 but ExceptionMessage says: "Self referencing loop detected for property 'Manager'" – Dmitriy Klyushin Jul 22 '18 at 01:37
  • @DmitriyKlyushin In EFDesigner, does it show the foreign key relationship with the two tables? https://msdn.microsoft.com/en-us/library/jj713564(v=vs.113).aspx – J Weezy Jul 22 '18 at 01:38
  • @JWeezy this is how it looks like in [EFDesigner](https://vgy.me/uYN435.png) – Dmitriy Klyushin Jul 22 '18 at 01:42
  • @DmitriyKlyushin It may be lazy loading. In your contact class, remove `virtual` for the manager class reference. Also, in the Context file, remove `virtual` from the two DbSets. – J Weezy Jul 22 '18 at 01:52
  • @JWeezy finally!!! removing `virtual` property lead to an error. But I found in [another post](https://stackoverflow.com/a/18223985/4429157) that one can add an attribute `[JsonIgnore]` to such virtual property - and it [worked](https://vgy.me/OKdUbS.png) for my case. Thanks for your help!!! I will add in an answer to this post with all modifications put together I had to add to make this work. – Dmitriy Klyushin Jul 22 '18 at 02:16
  • @DmitriyKlyushin You're welcome. Glad you were able to fix it. – J Weezy Jul 22 '18 at 02:28

1 Answers1

1

Thanks to @JWeezy, @DavidG and other guys from the comment section of the original post the solution was found:

Modifications needed:

disable lazy loading in the Context

Context

public partial class LightCRMEntities : DbContext
{
    public LightCRMEntities()
        : base("name=LightCRMEntities")
    {
        Configuration.LazyLoadingEnabled = false;
    }
// other code
}

Used eager loading in the repository

public class EFManagerRepository : IManagerRepository
{
    public IEnumerable<Manager> Managers
    {
        get
        {
            using (LightCRMEntities context = new LightCRMEntities())
            {
                return context.Managers.Include("ContactDetail").ToList();

            }
        }
    }
}

In the ContactDetail class added [JsonIgnore] attribute to the virtual property

public partial class ContactDetail
{
   //other properties
    [JsonIgnore]
    public virtual Manager Manager { get; set; }
}
Dmitriy Klyushin
  • 437
  • 1
  • 4
  • 17