ASP.NET Web API Dirty Tipps

Ein Kollege pingt mich am Freitag via Lync an. Er hat eine seltsame Fehlermeldung. Dank Lync wars ganz einfach, seinen Desktop zu sharen. Ahh - ASP.NET Web Api mit Datenbank generierten Entity Framework Model. In diesem Fall aus der Northwind Datenbank.

Der Ausschnitt aus der Fehlermeldung

{"Message":"Fehler","ExceptionMessage":"Fehler des Typs \"ObjectContent`1\"
beim Serialisieren des Antworttexts für den Inhaltstyp \"application/json;..

Ich sage nur, strukturierte Fehlersuche. Der JSON Serializer kommt relativ schnell ins straucheln wenn es sich um verschachtelte Daten handelt. Mit Zeile 13 wird der Serialisierer etwas großzügiger.

   1:  Public Module WebApiConfig
   2:      Public Sub Register(ByVal config As HttpConfiguration)
   3:          ' Web API configuration and services
   4:   
   5:          ' Web API routes
   6:          config.MapHttpAttributeRoutes()
   7:   
   8:          config.Routes.MapHttpRoute(
   9:              name:="DefaultApi",
  10:              routeTemplate:="api/{controller}/{id}",
  11:              defaults:=New With {.id = RouteParameter.Optional}
  12:          )
  13:          GlobalConfiguration.Configuration.Formatters.JsonFormatter.
SerializerSettings.ReferenceLoopHandling =
  14:  Newtonsoft.Json.ReferenceLoopHandling.Ignore
  15:   
  16:      End Sub

Im nächsten Schritt denkt man über die Relationen im OR Modell nach. Je mehr Tabellen verschachtelt werden, desto mehr Daten werden eingebettet vom Service zum Browser übertragen.

Mit einer Tabelle  Customers sind es 25KB Daten. Mit der Orders Tabelle verknüpft schon 314KB.

webapi4

Um dieses Verhalten zu steuern, erlaubt das Entity Framework das Laden der verschachtelten Daten zu verhindern.

In der Controller Klasse der Web API einfach Lazyloading deaktivieren.

   1:   Public Function GetValues() As IEnumerable(Of Customers)
   2:          Dim db As New NORTHWINDEntities
   3:          db.Configuration.LazyLoadingEnabled = False

Wie man im Json Code sehen kann, ist nun die Orders Relation vorhanden, aber leer.

webapi1

Das Standardverhalten des Browsers ist vermutlich auf Deinem Desktop anders. Um JSON Daten direkt anzuzeigen muss ein Registry Key gesetzt werden. Mit diesem Script  geht das ganz einfach(speichern als .reg)

[HKEY_CLASSES_ROOT\MIME\Database\Content Type\application/json]
"CLSID"="{25336920-03F9-11cf-8FD0-00AA00686F13}"
"Encoding"=hex:08,00,00,00

Allerdings gab es noch immer einen Fehler. Der Rückgabe Typ in der Web Api war keine generische List of Customers, sondern irgendwas mit

System.Data.Entity.DynamicProxies.Customers

Es gibt eine Menge Blog und Foreneinträge dazu unter anderem auch

Self referencing loop detected with type 'System.Data.Entity.DynamicProxies

Brock Allen schreibt dort man soll keine EF Typen zurück geben. Ich frage mich, für was soll ein ORM Tool sonst gut sein?

Jedenfalls habe ich das schon sehr oft mit Northwind gemacht und es hat immer funktioniert. Der Unterschied ist, das mein Kollege alle Tabellen ins Model eingefügt hat. Es muss also dort klemmen. Erst mit SQL Managment Studio und einem Datenbank Diagramm konnte ich das Problem erkennen. Es gibt dort eine Selbst Referenz.

webapi3

Solche benötigt man um Hierarchien in Tabellen abbilden zu können. Ein wenig stöbern im Web und MSDN ergibt, das sich Entity Framework in so einem Fall die Arbeit leichter macht und Proxy Klassen erzeugt. Kann man unterbinden mit ProxyCreation.

   1:  Public Function GetValues() As IEnumerable(Of Customers)
   2:          Dim db As New NORTHWINDEntities
   3:          db.Configuration.LazyLoadingEnabled = False
   4:          db.Configuration.ProxyCreationEnabled = False
   5:          Return db.Customers
   6:   End Function

Self Tracking Entities funktionieren dann nicht mehr. Verwende ich ohnehin nie.

Kommentare sind geschlossen