Reputation: 386
I´ve been looking for how avoid return a list without the attribute lazyLoader, I want to continue using the lazyLoader but I don´t want return the attribute when I return the whole list of my entity from my controller
I´m working with .NET core.
[
{
"lazyLoader": {},
"id": "id1"
"name": "name"
},
{
"lazyLoader": {},
"id": "id2",
"name": "name2"
}
]
Upvotes: 3
Views: 1844
Reputation: 2177
The checked answer for this question is just working for the root object, if we have many nested lazyloaded objects, this solution will not work. Although the answer of @Marcello-Barbiani is correct but it is not a good way to add this function to all entities we have.
The best way is create a new ContractResolver derived from DefaultContractResolver and check if property is Lazyloader then skip it as below:
public class NonLazyloaderContractResolver : DefaultContractResolver
{
public new static readonly NonLazyloaderContractResolver Instance = new NonLazyloaderContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.PropertyName == "LazyLoader")
{
property.ShouldSerialize = i => false;
}
return property;
}
}
after that adding above class pass it through JsonSerializerSettings while serializing the object:
var json = JsonConvert.SerializeObject(newProduct, new JsonSerializerSettings() {
ContractResolver = new NonLazyloaderContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore });
and finally if you are using asp.net core or asp.net core webapi add this contract as default contractresolver in startup.cs file:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
Upvotes: 1
Reputation: 11
I know this is old, but add
public boolean ShouldSerializeLazyLoader() { return false; }
to all the classes down the tree of the ones you want to serialize, and you will get a lazyloader free JSON.
Ref.: https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
Upvotes: 1
Reputation: 3557
In Entity Framework, if you have an object where one or more of its properties use lazy loading, check its runtime type name using GetType().Name. For an object of a Car class, for example, you will notice that the runtime type is actually something called CarProxy, which is a temporary in-memory type created by Entity Framework using reflection. This "fake" proxy class's base type is Car, and has all the original Car properties, but includes an extra one called LazyLoader for properties that may need it.
If you do further checking on this "fake" CarProxy type, you will also see that Assembly.IsDynamic = true, which is indicative that the class was created dynamically using reflection (see documentation):
var TheCar = DBContext.Cars.Find(1);
Console.WriteLine(TheCar.GetType().Assembly.IsDynamic.ToString()); //will echo "true"
Luckily, Newtonsoft.Json has an override on the JsonConvert.SerializeObject() method that allows us to provide a base type, so that the resulting JSON doesn't contain properties that don't exist in that type. So, to eliminate the LazyLoader property, just provide the object's BaseType as the type parameter:
var TheCar = DBContext.Cars.Find(1);
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType);
To make sure you don't get any circular reference loops when serializing (a very high probability when using lazy loading), call the serializer with the following setting:
var TheCar = DBContext.Cars.Find(1);
var Settings = new Newtonsoft.Json.JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType, Settings);
Note: This may only work on the first level deep when the serializer travels through the object. If there are yet more lazy-loading child properties of the object you provide to the serializer, the "LazyLoader" property may appear again. I haven't tested it so I can't say for sure.
Upvotes: 1
Reputation: 14133
You can do a select of you collection only retrieving the rest of the data. That way your objects will not have the Navigation property at all.
db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
Upvotes: 1