Web API - 返回复杂对象列表时出错
Web API - error when returning list of complex objects
我创建了一个如下所示的 webAPI 控制器方法:
[HttpGet]
public HttpResponseMessage RealEstates()
{
using (BoligsideDbContext context = new BoligsideDbContext())
{
List<RealEstateVm> realEstateVms = context.RealEstates.OrderByDescending(x => x.Id).ToList().Select(x => new RealEstateVm(x)).ToList();
return Request.CreateResponse(HttpStatusCode.OK, realEstateVms);
}
}
我的虚拟机如下所示:
public class RealEstateVm
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int Area { get; set; }
public int Rooms { get; set; }
public int Rent { get; set; }
public string Picture { get; set; }
public RealEstateType Type { get; set; } //this is just an enum
public string Address { get; set; }
public List<string> Images { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Phone2 { get; set; }
public string OriginalUrl { get; set; }
public string OriginalSource { get; set; }
public string City { get; set; }
public int ZipCode { get; set; }
public string StreetAddress { get; set; }
public double Longtitude { get; set; }
public double Latitude { get; set; }
}
然而,每当我到达端点时,我都会收到以下错误:
Type 'Boligside.ViewModels.RealEstateVm' cannot be serialized.
Consider marking it with the DataContractAttribute attribute, and
marking all of its members you want serialized with the
DataMemberAttribute attribute. If the type is a collection, consider
marking it with the CollectionDataContractAttribute. See the Microsoft
.NET Framework documentation for other supported types.
可能是什么问题?我不明白为什么我必须用 [DataContractAttribute]?
标记我的 VM
顺便说一句,完整的错误信息在这里:
This XML file does not appear to have any style information associated
with it. The document tree is shown below. An error
has occurred. The 'ObjectContent`1' type
failed to serialize the response body for content type
'application/xml; charset=utf-8'.
System.InvalidOperationException
An error has
occurred. Type
'Boligside.ViewModels.RealEstateVm' cannot be serialized. Consider
marking it with the DataContractAttribute attribute, and marking all
of its members you want serialized with the DataMemberAttribute
attribute. If the type is a collection, consider marking it with the
CollectionDataContractAttribute. See the Microsoft .NET Framework
documentation for other supported types.
System.Runtime.Serialization.InvalidDataContractException
at
System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String
message, Type type) at
System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32
id, RuntimeTypeHandle typeHandle, Type type) at
System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32
id, RuntimeTypeHandle typeHandle, Type type) at
System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(Int32
id, RuntimeTypeHandle typeHandle) at
System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator
xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType,
Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) at
WriteArrayOfRealEstateVmToXml(XmlWriterDelegator , Object ,
XmlObjectSerializerWriteContext , CollectionDataContract ) at
System.Runtime.Serialization.CollectionDataContract.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.WriteToStream(Type
type, Object value, Stream writeStream, HttpContent content) at
System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type
type, Object value, Stream writeStream, HttpContent content,
TransportContext transportContext, CancellationToken
cancellationToken) --- End of stack trace from previous location where
exception was thrown --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()
如错误所说,无法序列化,考虑添加数据契约属性..
using System.Runtime.Serialization;
[DataContract]
public class RealEstateVm
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public int Area { get; set; }
[DataMember]
public int Rooms { get; set; }
[DataMember]
public int Rent { get; set; }
[DataMember]
public string Picture { get; set; }
[DataMember]
public RealEstateType Type { get; set; } //this is just an enum
public string Address { get; set; }
[DataMember]
public List<string> Images { get; set; }
public string Name { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string Phone { get; set; }
[DataMember]
public string Phone2 { get; set; }
[DataMember]
public string OriginalUrl { get; set; }
[DataMember]
public string OriginalSource { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public int ZipCode { get; set; }
[DataMember]
public string StreetAddress { get; set; }
[DataMember]
public double Longtitude { get; set; }
[DataMember]
public double Latitude { get; set; }
}
的更多信息
您的 DTO class 缺少无参数构造函数。看这里:Why XML-Serializable class need a parameterless constructor
(很抱歉打醒这个问题,但我现在也有同样的问题)
从浏览器调用 API 不会将 Accept Header 设置为 application/json,因此 api 将使用默认使用 DataContractSerializer 的 XmlFormatter,这是可选的。
您可以像这样更改 XML 的默认行为
// XML Serializer Settings
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
// use UseXmlSerializer because we use opu-out in our model classes
xml.UseXmlSerializer = true;
我创建了一个如下所示的 webAPI 控制器方法:
[HttpGet]
public HttpResponseMessage RealEstates()
{
using (BoligsideDbContext context = new BoligsideDbContext())
{
List<RealEstateVm> realEstateVms = context.RealEstates.OrderByDescending(x => x.Id).ToList().Select(x => new RealEstateVm(x)).ToList();
return Request.CreateResponse(HttpStatusCode.OK, realEstateVms);
}
}
我的虚拟机如下所示:
public class RealEstateVm
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int Area { get; set; }
public int Rooms { get; set; }
public int Rent { get; set; }
public string Picture { get; set; }
public RealEstateType Type { get; set; } //this is just an enum
public string Address { get; set; }
public List<string> Images { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Phone2 { get; set; }
public string OriginalUrl { get; set; }
public string OriginalSource { get; set; }
public string City { get; set; }
public int ZipCode { get; set; }
public string StreetAddress { get; set; }
public double Longtitude { get; set; }
public double Latitude { get; set; }
}
然而,每当我到达端点时,我都会收到以下错误:
Type 'Boligside.ViewModels.RealEstateVm' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
可能是什么问题?我不明白为什么我必须用 [DataContractAttribute]?
标记我的 VM顺便说一句,完整的错误信息在这里:
This XML file does not appear to have any style information associated with it. The document tree is shown below. An error has occurred. The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'. System.InvalidOperationException An error has occurred. Type 'Boligside.ViewModels.RealEstateVm' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types. System.Runtime.Serialization.InvalidDataContractException at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(Int32 id, RuntimeTypeHandle typeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) at WriteArrayOfRealEstateVmToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract ) at System.Runtime.Serialization.CollectionDataContract.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.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()
如错误所说,无法序列化,考虑添加数据契约属性..
using System.Runtime.Serialization;
[DataContract]
public class RealEstateVm
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public int Area { get; set; }
[DataMember]
public int Rooms { get; set; }
[DataMember]
public int Rent { get; set; }
[DataMember]
public string Picture { get; set; }
[DataMember]
public RealEstateType Type { get; set; } //this is just an enum
public string Address { get; set; }
[DataMember]
public List<string> Images { get; set; }
public string Name { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string Phone { get; set; }
[DataMember]
public string Phone2 { get; set; }
[DataMember]
public string OriginalUrl { get; set; }
[DataMember]
public string OriginalSource { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public int ZipCode { get; set; }
[DataMember]
public string StreetAddress { get; set; }
[DataMember]
public double Longtitude { get; set; }
[DataMember]
public double Latitude { get; set; }
}
的更多信息
您的 DTO class 缺少无参数构造函数。看这里:Why XML-Serializable class need a parameterless constructor (很抱歉打醒这个问题,但我现在也有同样的问题)
从浏览器调用 API 不会将 Accept Header 设置为 application/json,因此 api 将使用默认使用 DataContractSerializer 的 XmlFormatter,这是可选的。
您可以像这样更改 XML 的默认行为
// XML Serializer Settings
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
// use UseXmlSerializer because we use opu-out in our model classes
xml.UseXmlSerializer = true;