12

Guys I have a One to many relation to same class called user,
I am returning one instance of user in web apis get method it works fine as far as I don't have any

User 

ID  | Name 
0   | A 
1   | B 

Friends Table ( This table is used to build the one to many relationship ) 

User_ID | Friend_ID 
 1      |     0 
 0      |     1 

This is my GetMethod

[HttpGet]
        public Models.User   Authenticate()
        {
            try
            {
                return   db.Users.SingleOrDefault(x => x.ID == 0 ) ; 
            } 
            catch
            {
                return null;
            }
        }

If I get and return a User entity then I get the blow error

Can anyone please help me to fix this below error ?

{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'text/html; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected with type 'System.Data.Entity.DynamicProxies.Friend_E5C79F4736EB2750392FFC7061B18E9C12F15F9583409603C75C5D1B1F7358D4'. Path 'Friends1[0].User.Friends'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":" at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value)\r\n at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value)\r\n at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)\r\n at System.Net.Http.Formatting.JsonMediaTypeFormatter.<>c__DisplayClassd.b__c()\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token)"}}

Nasreddine
  • 36,610
  • 17
  • 75
  • 94
Kas
  • 3,747
  • 5
  • 29
  • 56
  • Updated my Question , I have added my GetMethod to the question – Kas Oct 29 '13 at 16:48
  • Actully , I am using a Guid as ID ,But in my question i said it as an int field , because I am thinking that the error is not causing because of the guide , however I am expecting a good solution from someone :) – Kas Oct 29 '13 at 16:49
  • Can you try exec query and don't return noting, it seems you have error in you models. Try this: var t = db.Users.SingleOrDefault(x => x.ID == 0); return (User)null; – alexmac Oct 29 '13 at 16:51
  • This returns the User with ID zero , But it doesn't return from web-api , I am requesting json format as return type of web-api , I was debugging the get method , And I can get the correct user entity, but when return it from web-api , I get that error – Kas Oct 29 '13 at 16:53
  • Show me your models User and Friend – alexmac Oct 29 '13 at 16:54
  • My Model & User classes are slightly complex than the one I showed for the question – Kas Oct 29 '13 at 16:55
  • Try decorating your models with `[DataContract(IsReference = true)]` – Aidin Oct 29 '13 at 17:56
  • Aidin , that didn't help , I can see only id in result when i decorate my model with DataContract(IsReference = true) – Kas Oct 30 '13 at 02:48

2 Answers2

31

Try to change webApi formatter. Add these lines in WebApiConfig.cs:

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

And add this line:

json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
alexmac
  • 19,087
  • 7
  • 58
  • 69
13

Apply the [JsonIgnore] attribute to the navigation property you don't want to be serialised. It will still serialise both the parent and child entities but just avoids the self referencing loop.

B-Lat
  • 1,685
  • 1
  • 18
  • 25
  • How do you do this with DB first EF? – seebiscuit Aug 12 '16 at 17:56
  • As far as I'm aware it's the same. I was using DB first, so unless you're using a generator to keep regenerating your domain objects from the database, then the above should work. – B-Lat Aug 23 '16 at 09:45
  • That's the issue; _I am_ using a generator :( and it gets updated every once in a while when there's a schema change... I remember seeing a workaround with partials, though. – seebiscuit Aug 23 '16 at 10:17
  • Here is how you add attributes in a separate class that works with generated code...[https://stackoverflow.com/questions/16736494/add-data-annotations-to-a-class-generated-by-entity-framework/40666910#40666910] – Carter Medlin Aug 06 '18 at 22:55