Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Json.NET from using the Entity Framework proxy type name?

In my design I have a class that has a property whose type can be inherited from:

public class Feed
{
    ...
    [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)]
    public FeedSource Source { get; set; }
    ...
}

public abstract class FeedSource { ... }

public class CsvSource : FeedSource { ... }

public class DbSource : FeedSource { ... }

I'm using the Entity Framework to load and store this object to a database and I'm using Json.NET to serialize this object into JSON for further processing.

The problem I stumbled on is that the $type property is containing the typename of the EF proxy instead of the "real" typename. So instead of:

$type: "System.Data.Entity.DynamicProxies.CsvSource_0B3579D9BE67D7EE83EEBDDBFA269439AFC6E1122A59B4BB81EB1F0147C7EE12"

which is meaningless to other clients, I would like to get:

$type: "MyNamespace.CsvSource"

in my JSON.

What's the best way to achieve this?

like image 991
Dejan Avatar asked Jun 06 '14 12:06

Dejan


People also ask

How to convert entity type to JSON in Entity Framework?

The database is just being used to store parts of your domain. Instead you can use EF Core's HasConversion () method on the EntityTypeBuilder object to convert between your type and JSON.

How do I prevent Entity Framework from creating proxy instances?

Sometimes it is useful to prevent Entity Framework from creating proxy instances. For example, serializing non-proxy instances is considerably easier than serializing proxy instances. Proxy creation can be turned off by clearing the ProxyCreationEnabled flag. One place you could do this is in the constructor of your context.

How do I find the entity type of a proxy type?

You can find the entity type for this proxy type using the GetObjectType method from ObjectContext. For example: Note that if the type passed to GetObjectType is an instance of an entity type that is not a proxy type then the type of entity is still returned.

What does the create method do in Entity Framework?

Note that the Create method will just create an instance of the entity type itself if creating a proxy type for the entity would have no value because it would not do anything. For example, if the entity type is sealed and/or has no virtual properties then Create will just create an instance of the entity type.


2 Answers

Another way which doesn't require you to make changes to your EF configuration is to use a custom SerializationBinder, e.g.:

class EntityFrameworkSerializationBinder : SerializationBinder
{
    public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = null;

        if (serializedType.Namespace == "System.Data.Entity.DynamicProxies")
            typeName = serializedType.BaseType.FullName;
        else
            typeName = serializedType.FullName;
    }

    public override Type BindToType(string assemblyName, string typeName)
    {
        throw new NotImplementedException();
    }
}

Usage:

string json = JsonConvert.SerializeObject(entityFrameworkObject, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, Binder = new EntityFrameworkSerializationBinder() });
like image 52
bambam Avatar answered Oct 24 '22 07:10

bambam


You can do two things:

  • disabling tracking proxies, by setting ProxyCreationEnabled to false. You can find this property in your context's Configuration property. If you use a context for a single GetXxx method, you can do it without interfering other context instanced.

  • using the AsNoTracking() extension method when you recover your entity, like this:

    MyContext.MyTable.AsNoTracking(). // rest of the query here

This indicates that you don't want a tracking proxy for your entity, so you'll get the entity class. This has no interference with the afore mentioned configuration.

like image 38
JotaBe Avatar answered Oct 24 '22 08:10

JotaBe