Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Wednesday, December 30, 2015

Circular reference detected exception while serializing object to JSON

Circular reference detected exception while serializing object to JSON


Just as mentioned in this post, I am getting a Json serialization error while serializing an Entity Framework Proxy:

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.PurchaseOrder_446B939192F161CDBC740067F174F7A6059B0F9C0EEE68CD3EBBD63CF9AF5BD0'.

But the difference is, I don't have a circular reference in my entities, and it only occurs in our production environment. Locally everything works fine...

My Entities:

public interface IEntity  {      Guid UniqueId { get; }      int Id { get; }  }     public class Entity : IEntity  {      public int Id { get; set; }      public Guid UniqueId { get; set; }  }    public class PurchaseOrder : Entity  {      public string Username { get; set; }      public string Company { get; set; }        public string SupplierId { get; set; }      public string SupplierName { get; set; }        public virtual ICollection Lines { get; set; }  }    public class PurchaseOrderLine : Entity  {      public string Code { get; set; }      public string Name { get; set; }      public decimal Quantity { get; set; }  }  

The GetCurrent action on my PurchaseOrderController throwing the exception:

public class PurchaseOrderController : Controller  {      private readonly IUnitOfWork _unitOfWork;        public PurchaseOrderController(IUnitOfWork unitOfWork)      {          _unitOfWork = unitOfWork;      }        public JsonResult GetCurrent()      {          return Json(EnsurePurchaseOrder(), JsonRequestBehavior.AllowGet);      }        private PurchaseOrder EnsurePurchaseOrder()      {          var company = RouteData.GetRequiredString("company");          var repository = _unitOfWork.GetRepository();            var purchaseOrder = repository                  .Include(p => p.Lines)                  .FirstOrDefault                  (                      p => p.Company == company &&                            p.Username == User.Identity.Name                  );            if (purchaseOrder == null)          {              purchaseOrder = repository.Create();              purchaseOrder.UniqueId = Guid.NewGuid();              purchaseOrder.Company = company;              purchaseOrder.Username = User.Identity.Name;              _unitOfWork.SaveChanges();          }            return purchaseOrder;      }  }  

Answer by Radu Popovici - Oncica for Circular reference detected exception while serializing object to JSON


Your POCO entities are perfectly serializable. Your problem is that the dynamic proxies the EF runtime creates for you are usually not. You can set the context.Configuration.ProxyCreationEnabled to false but then you lose lazy loading. My strong recommendation to you is to use Json.NET which supports serialization for EF entities:

http://james.newtonking.com/archive/2009/07/10/ado-net-entity-framework-support-accidently-added-to-json-net.aspx

http://james.newtonking.com/projects/json-net.aspx

Answer by Erik Philips for Circular reference detected exception while serializing object to JSON


Option 1 (recommended)

Try turning off Proxy object creation on your DbContext.

DbContext.Configuration.ProxyCreationEnabled = false;  

Typically this scenario is because the application is using POCO objects (Either T4 Generated or Code-First). The problem arises when Entity Framework wants to track changes in your object which is not built into POCO objects. To resolve this, EF creates proxy objects which lack the attributes in the POCO objects, and aren't serializable.

The reasons why I recommend this approach; using a website means that you probably don't need change tracking (stateful) on Entity Framework objects, it free's up memory and cpu because change tracking is disabled and it will work consistantly on all your objects the same way.

Option 2

Use a serializer (like JSON.Net which is already included in ASP.Net 4) that allows customization to serialize the object(s).

The reasons I do not recommend this approach is that eventually custom object serialization logic will be need to serial proxy objects as other objects types. This means you have a dependency on logic to deliver a result downstream. Changing the object means changing logic, and in an ASP.Net MVC project (any version) instead of only changing a View you have some thing else to change that is not readily known outside of whoever wrote the logic first.

Option 3 (Entity Framework 5.x +)

Use .AsNoTracking() which will disable the proxy objects on the specific query. If you need to use change tracking, this allows a nice intermediate solution to solution #1.

Answer by NicoJuicy for Circular reference detected exception while serializing object to JSON


The circular reference happens because you use eager loading on the object.

You have 3 methods:

  • Turn off eager loading when your loading your Query (linq or lambda) DbContext.Configuration.ProxyCreationEnabled = false;
  • Detach the objects (= no eager loading functionality & no proxy)
    • Repository.Detach(entityObject)
    • DbContext.Entry(entityObject).EntityState = EntityState.Detached
  • Clone the properties
    • You could use something like AutoMapper to clone the object, don't use the ICloneable interface, because it also clones the ProxyProperties in the object, so that won't work.
  • In case you are building an API, try using a separte project with a different configuration (that doesn't return proxies)

PS. Proxies is the object that's created by EF when you load it from the Entity Framework. In short: It means that it holds the original values and updated values so they can be updated later. It handles other things to ;-)

Answer by Freestyle076 for Circular reference detected exception while serializing object to JSON


I had the same error, however I saw it both on production server and locally. Changing the DbContext configuration didn't quite solve my issue. A different solution was presented to me with the

[IgnoreDataMember]  

attribute on DB entity references. See the post here if this sounds more pertinent to your issue.

ASP.NET Web API Serialized JSON Error: "Self Referencing loop"

Answer by Marco for Circular reference detected exception while serializing object to JSON


I had the same problem and resolved it by un-checking Json.NET in the project Extensions in the Reference Manager.

(see the image http://i.stack.imgur.com/RqbXZ.png)

I also had to change the project.csproj file to map the correct path for the new version:

    ..\packages\Newtonsoft.Json.6.0.5\lib\net45\Newtonsoft.Json.dll    

and still had to configure the web.config

                    

Note that in the web.config file I was forced to refer to the OLDER (6.0.0.0) version though the installed version was 6.0.5.

Hope it helps!

Answer by Ali Adravi for Circular reference detected exception while serializing object to JSON


Whatever classes have the reference of other class just add attribute like this

[Newtonsoft.Json.JsonIgnoreAttribute]  public virtual ICollection Lines { get; set; }  

Now everything work smooth

Answer by PimBrouwers for Circular reference detected exception while serializing object to JSON


I spent countless hours attempting all of the various solutions I found scattered throughout the web, including:

  • [JsonIgnore]
  • Internal Getters
  • Disabling LazyLoadingEnabled and ProxyCreationEnabled
  • Setting ReferenceLoopHandling to "ignore"
  • Carefully using explicit loading where needed

All of which ultimately proved fruitless for me. Ignoring a property helped one query, but hurt 3 others. It felt like the programming equivalent to whack-a-mole.

The context of my problem was that the data going in an out of my application had to be JSON. No way around it. Inserts and updates obviously pose much less of a problem. But selecting data that's stored in a normalized database (and in my case including a version history) to be serialized is a nightmare.

The solution:

Return the data (properties) you need as anonymous objects.

A code example:

In this case I needed the 3 latest tickets, based on "Date Scheduled". But also needed several properties stored in related entities.

var tickets =       context.TicketDetails      .Where(t => t.DateScheduled >= DateTime.Now)      .OrderBy(t => t.DateScheduled)      .Take(3)      .Include(t => t.Ticket)      .Include(t => t.Ticket.Feature)      .Include(t => t.Ticket.Feature.Property)      .AsEnumerable()      .Select(          t =>          new {              ID = t.Ticket.ID,              Address = t.Ticket.Feature.Property.Address,              Subject = t.Ticket.Subject,              DateScheduled = String.Format("{0:MMMM dd, yyyy}", t.DateScheduled)      }  );  

And voila, no self referencing loops.

I realize this situation may not be adequate in all cases given that entities and objects may change. But it's certainly worth some consideration if all else fails.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.