2013-01-24 161 views
2

我有一個完整的MVC4網站,今天我試圖添加一個Web API,但沒有成功。ASP.NET Web Api System.Runtime.Serialization.SerializationException

<Error> 
<Message>An error has occurred.</Message> 
<ExceptionMessage> 
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'. 
</ExceptionMessage> 
<ExceptionType>System.InvalidOperationException</ExceptionType> 
<StackTrace/> 
<InnerException> 
<Message>An error has occurred.</Message> 
<ExceptionMessage> 
Type 'System.Data.Entity.Infrastructure.DbQuery`1[[LeasingWeb.Models.Car, LeasingWeb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ArrayOfCar:http://schemas.datacontract.org/2004/07/LeasingWeb.Models' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer. 
</ExceptionMessage> 
<ExceptionType> 
System.Runtime.Serialization.SerializationException 
</ExceptionType> 
<StackTrace> 
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) at WriteCarDBToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract) at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.<>c__DisplayClass7.<WriteToStreamAsync>b__6() at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token) 
</StackTrace> 
</InnerException> 
</Error> 

我的對象是這些:

public class Image 
{ 
    public int ID { get; set; } 

    [Required(ErrorMessage="Please select a car")] 
    [ForeignKey("Car")] 
    public int CarID { get; set; } 

    [DisplayName("Picture")] 
    [Required] 
    [FileExtensions(ErrorMessage = "Please specify a valid image file (.jpg, .jpeg, .gif or .png)", Extensions = ("jpg,png,jpeg"))] 
    public string Name { get; set; } 


    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    public int ID { get; set; } 

    [Required] 
    [DisplayName("Car Model")] 
    public string Name { get; set; } 

    [Required] 
    public string Company { get; set; } 

    [Required] 
    [DisplayName("Car Type")] 
    [ForeignKey("CarType")] 
    public int CarTypeID { get; set; } 

    [Required] 
    [Range(1,5)] 
    [DisplayName("Number Of Doors")] 
    public float NumDoors { get; set; } 

    [Required] 
    [Range(0, Int32.MaxValue)] 
    public float Acceleration { get; set; } 

    public virtual CarType CarType { get; set; } 
} 

public class CarType 
{ 
    [Key] 
    public int ID { get; set; } 

    [Required] 
    [DataType(DataType.Text)] 
    public string Type { get; set; } 
} 

並持有它們的對象即:

public class CarDB 
{ 
    public IQueryable<Car> Cars { get; set; } 
    public IEnumerable<Image> Images { get; set; } 
} 

的API控制器:

public CarDB Get(int ID = -1) 
{ 
    CarDB car = new CarDB(); 
    if (ID == -1) 
    { 
     car = new CarDB { Cars = db.Cars.Include(c => c.CarType), Images = db.Images }; 
    } 
    else 
    { 
     car = new CarDB { Cars = db.Cars.Where(c => c.ID == ID).Include(c => c.CarType), Images = db.Images.Where(c => c.CarID == ID) }; 
    } 
    return car; 
} 

由於任何人可以幫幫我。

回答

4

這裏的問題是CarDB對象上的Cars成員。 DataContractSerializer特殊情況集合接口(如IEnumerable和IList),但它並不像IQueryable那樣是特殊情況派生的接口。對於這些接口,它們被視爲類型是對象,任何實現都必須聲明爲已知類型。

您可以嘗試通過將IQueryable<Car>成員更改爲IEnumerable<Car>來解決此問題。

+0

我需要爲[KnownType]添加什麼參考? 無法找到類型或命名空間名稱'KnownTypeAttribute'(您是否缺少使用指令或程序集引用?) – Chen

+0

System.Runtime.Serialization –

+0

我有點感到愚蠢,但我仍然無法讓它甚至接受[KnownType]的屬性,即使有該引用,它也不會將其確認爲有效的命令。 (如果它只是一個「使用」標籤VS2012會自動提供) – Chen

0

我使用30個包含大約40個具有延遲加載的外鍵的遺留代碼存在此問題。我發現它更容易,而不是爲所有數據庫類添加更多註釋,只需創建一個包含我想要返回的字段的ViewModel。 如果返回的數據很複雜,那麼我建議使用automapper。