EF 4 Entity mit Json.Net Serialisieren
Kleiner Trick zum Serialisieren von Entity-Framework Objekten mit Newtonsoft Json.NetDas Entity-Framework generiert für die Entity-Klassen Proxies, die den Zugriff auf virtuelle Properties und Collections kapseln. Diese Proxy-Klassen werden per Reflection.Emit zur Laufzeit erzeugt. Hiermit kann Newtonsoft Json.Net leider nichts anfangen.
Diese ausgezeichnete Bibliothek zur Serialisierung von .Net Objekten nach Json und vice-versa bietet aber vielseitige Erweiterungsmöglichkeiten, so dass auch das oben genannte Problem umschifft werden kann.
Um also zu verhindern, dass Json.Net versucht eine Property eine Proxy-Klasse zu serialisieren (was zu einer Exception führt), dürfen nur Member-Variablen mit bekannten Typen beachtet werden. Hierzu kann in den JsonSerializerSettings ein IContractResolver angegeben werden:
var settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, TypeNameHandling = TypeNameHandling.Objects, ContractResolver = new EFContractResolver() }; var json = JsonConvert.SerializeObject(query, Formatting.Indented, settings);
Der EFContractResolver verhält sich im grossen und ganzen wie der Json.Net DefaultContractResolver. Dieser enthält eine überschreibbare Methode GetSerializableMembers in der diejenigen Member eines Typs eingeschlossen werden, die in der Json-Ausgabe wieder aufsuchen sollen. Da wir die zusätzlichen Member des Proxies ignorieren wollen, nutzen wir die Fähigkeit der EF-ObjectContext auf alle Entity-Proxy-Abbildungen innerhalb einer App-Domain zuzugreifen:
public class EFContractResolver : DefaultContractResolver { protected override ListGetSerializableMembers(Type proxyType) { var knownProxyTypes = ObjectContext.GetKnownProxyTypes(); if (!knownProxyTypes.Contains(proxyType)) return base.GetSerializableMembers(proxyType); var entityType = ObjectContext.GetObjectType(proxyType); return base.GetSerializableMembers(entityType); } }
An dieser Stelle sind natürlich noch andere Filter-Möglichkeiten denkbar, z.B. Sichtbarkeit per Display-Attribut oder die Zugriffssteuerung per Authorize-Attribut.