Ef4 reason circular link in web service

I have a Reason object:

public class Reason { public virtual long Id { get; set; } public virtual string Name { get; set; } public virtual Company Company {get;set;} } 

I use the framework 4 entity, and the company is a navigation property for the Company.
I also use webservices to return data to the client.
I have a web method that returns the reasons:

  [WebMethod] public Reason[] GetCallReasons() { IReasonRepository rep = ObjectFactory.GetInstance<IReasonRepository>(); return rep.GetReasonsList().ToArray(); } 

Due to ef4, I get the following exception for executing the web method:

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

The problem is that ef4 adds a property that cannot be serialized: Image of the watch panel on rep.GetReasonsList (). ToArray ()

To solve this problem and fix the error, I can turn off the navigation property without making it virtual or deleting the navigation property. But I understand it and want to use the lazy boot function.

I can also write a special serializer for Reason, but I have many classes that I used in my web services, and writing a serializer for all of them is a lot of work.

How can I resolve this exception? ..

+4
source share
3 answers

There are several solutions to your problem, and they really depend on the type of service you are using and the type of serialization:

  • The clean approach uses DTO (data transfer objects), as @Mikael has already suggested. DTO is a special object that conveys exactly what you need, and nothing more. You can simply create a DTO so that it does not contain circular references and use AutoMapper to map between entities and DTO and vice versa. +1 for @Mikael because he was the first to mention it.

All other approaches are based on tweeking serialization, as @Haz suggested:

  • WCF and DataContractSerializer : explicitly mark your objects with DataContract[IsReference=true] and all properties with [DataMember] . This will allow you to use circular links. If you use the T4 template to create objects, you must modify it to add these attributes for you.
  • WCF and DataContractSerializer : Implicit Serialization. Check one of the associated navigation properties with the [IgnoreDataMember] attribute so that the property is not serialized.
  • XmlSerializer : check one of the associated navigation properties with the [XmlIgnore] attribute
  • Other serializations: Mark one of the related navigation properties with [NonSerialized] (+1 for Haz, which he was the first to mention it) for general serialization, or [ScriptIgnore] for some JSON related serialization.
+11
source

I usually write specific classes for a web service. Although this is an additional work, it has the advantage that the web service becomes more reliable, as small changes in your objects will not remain invisible and silently go to the side of the user / javascript. For example, if I change the name of a property.

There are a few things you can do to reduce work, and one is to use AutoMapper, which can automatically match objects.

+8
source

You have not provided a definition for your corporate class ... But I assume that you have a collection of Reason as a property.

Lazy loading in SOA Enviroment doesn't actually work. You cannot have unlimited lazy navigation around the serialized class, as soon as you leave the web method, you have no way to call back to the original datacontext from the consumer of the web method to find the properties you need ... so the serializer will try to find all the properties, including lazy properties during serialization.

You need to disable serialization for one part of the circular link, either in the Reason collection in the Company class or in the company in the Reason class.

You can use the NotSerialized attribute to disable serialization of a specific field.

+4
source

All Articles