2012-12-19 3 views
33

Einfachstes Beispiel dafür, erhalte ich eine Sammlung und versuchen Sie es über Web-API zur Ausgabe:Asp.Net-Web-API-Fehler: Der Typ "ObjectContent" 1 konnte den Antworttext für den Inhaltstyp "application/xml" nicht serialisieren. charset = utf-8'

// GET api/items 
public IEnumerable<Item> Get() 
{ 
    return MyContext.Items.ToList(); 
} 

Und ich bekomme die Fehlermeldung:

Object of type
'System.Data.Objects.ObjectQuery`1[Dcip.Ams.BO.EquipmentWarranty]' cannot be converted to type
'System.Data.Entity.DbSet`1[Dcip.Ams.BO.EquipmentWarranty]'

Dies ist eine hübsche häufiger Fehler mit den neuen Proxies zu tun, und ich weiß, dass ich es durch das Setzen beheben können:

MyContext.Configuration.ProxyCreationEnabled = false; 

Aber das besiegt den Zweck eine Menge von dem, was ich zu tun versuchen. Gibt es einen besseren Weg?

+1

Wie Wird beim Proxy-Server das Serialisieren eines Objekts deaktiviert? –

+0

Es ist ein Proxy-Objekt, nicht das eigentliche POCO. – naspinski

+0

Wenn Sie den Proxy global deaktivieren, können Sie keine Lazy-Loaded-Navigationseigenschaften verwenden. Ich stimme zu, dass dies keine richtige Lösung ist, wenn Sie die Navigationseigenschaften benötigen. Suche immer noch nach einer Antwort für dieses Problem. – Paul

Antwort

23

Ich würde vorschlagen, Proxy-Erstellung nur an der Stelle deaktivieren, wo Sie nicht brauchen oder Probleme verursacht. Sie müssen es nicht deaktivieren global können Sie nur den aktuellen DB Kontext über den Code deaktivieren ...

[HttpGet] 
    [WithDbContextApi] 
    public HttpResponseMessage Get(int take = 10, int skip = 0) 
    { 
     CurrentDbContext.Configuration.ProxyCreationEnabled = false; 

     var lista = CurrentDbContext.PaymentTypes 
      .OrderByDescending(x => x.Id) 
      .Skip(skip) 
      .Take(take) 
      .ToList(); 

     var count = CurrentDbContext.PaymentTypes.Count(); 

     return Request.CreateResponse(HttpStatusCode.OK, new { PaymentTypes = lista, TotalCount = count }); 
    } 

hier nur ich die ProxyCreation in dieser Methode deaktiviert, da für jede Anforderung gibt es eine neue DbContext ist erstellt und Daher habe ich die ProxyCreation nur für diesen Fall deaktiviert. Hoffe, es hilft

+0

das ist toll, danke – Salim

12

Wenn Sie Navigationseigenschaften haben, machen Sie sie nicht virtuell. Mapping wird immer noch funktionieren, aber es verhindert die Erstellung von Dynamic Proxy-Entities, die nicht serialisiert werden können.]

In einem WebApi ist kein Lazy Loading möglich, da Sie keine persistente Verbindung haben und trotzdem eine .ToList() ausgeführt haben .

+1

Ich hatte das gleiche Problem und die Navigationseigenschaften nicht virtuell macht den Trick, aber ich bin neugierig zu wissen, ob es irgendwelche Nachteile dieser Technik gibt? Vielen Dank! – Robert

+5

@Robert markiert sie als virtual ermöglicht die Klasse intern überschrieben werden. EF wird überschreiben, um das verzögerte Laden zu ermöglichen. Zum Beispiel werden nur interne Listen oder Eigenschaften abgerufen, wenn sie angefordert werden. Im Fall von MVC oder etwas, wo es keine Verbindung Architektur gibt es keinen Unterschied, wie Sie alle Daten sofort benötigen. – Oliver

23

Wenn Sie Navigationseigenschaften haben und nicht wollen, dass sie nicht virtuell sind, sollten Sie JSON.NET verwenden und die Konfiguration in App_Start so ändern, dass JSON und nicht XML verwendet wird!
nach JSON.NET Von NuGet installieren, legen Sie diesen Code in WebApiConfig.cs in Register-Methode

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

es funktioniert für mich, danke – kn3l

+1

danke, es funktioniert. – daylight

+0

Das Hinzufügen des Codes in der Konfiguration funktioniert. Angenommen, JSON.NET wird standardmäßig mit dem neuen Webapi-Projekt auf VS15 hinzugefügt. – shaikhspear

3

In meinem Fall das Objekt mußten mit einem Typ in ihm eine Eigenschaft zurückgegeben wird, die kein argument/default hatte Konstrukteur. Durch Hinzufügen eines Nullargumentkonstruktors zu diesem Typ konnte das Objekt erfolgreich serialisiert werden.

+0

Das löste das Problem für mich. –

6

ich nur deaktiviert Proxy-Klassen auf einer Pro-needed Basis:

// GET: ALL Employee 
    public IEnumerable<DimEmployee> Get() 
    { 
     using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities()) 
     { 
      entities.Configuration.ProxyCreationEnabled = false; 
      return entities.DimEmployees.ToList(); 
     } 
    } 
4

Das half mir:
Fügen Sie den folgenden Code in Application_Start Funktion von Global.asax.cs

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings 
    .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
GlobalConfiguration.Configuration.Formatters 
    .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 
+0

Bitte fügen Sie auch Erklärung hinzu. – Unbreakable