【问题标题】:Web API - error when returning list of complex objectsWeb API - 返回复杂对象列表时出错
【发布时间】:2016-05-14 20:35:49
【问题描述】:

我创建了一个如下所示的 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; }
}

但是,每当我转到端点时,我都会收到以下错误:

类型“Boligside.ViewModels.RealEstateVm”无法序列化。 考虑使用 DataContractAttribute 属性对其进行标记,并且 标记您想要序列化的所有成员 DataMemberAttribute 属性。如果类型是集合,请考虑 用 CollectionDataContractAttribute 标记它。见微软 其他受支持类型的 .NET Framework 文档。

可能是什么问题?我不明白为什么我必须用 [DataContractAttribute] 标记我的 VM?

顺便说一下完整的错误信息在这里:

此 XML 文件似乎没有关联任何样式信息 用它。文档树如下所示。一个错误 已经发生了。 'ObjectContent`1' 类型 未能序列化内容类型的响应正文 '应用程序/xml;字符集=utf-8'。 System.InvalidOperationException 有一个错误 发生了。类型 'Boligside.ViewModels.RealEstateVm' 无法序列化。考虑 用 DataContractAttribute 属性标记它,并标记所有 您希望使用 DataMemberAttribute 序列化的成员 属性。如果类型是集合,请考虑使用 集合数据合同属性。请参阅 Microsoft .NET 框架 其他支持类型的文档。 System.Runtime.Serialization.InvalidDataContractException 在 System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(字符串 消息,类型类型)在 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) 在 System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 声明类型 ID,RuntimeTypeHandle 声明类型句柄)在 WriteArrayOfRealEstateVmToXml(XmlWriterDelegator,对象, XmlObjectSerializerWriteContext , CollectionDataContract )在 System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter,对象 obj,XmlObjectSerializerWriteContext 上下文)在 System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, 对象 obj, RuntimeTypeHandle 声明的TypeHandle) 在 System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, 对象 obj, RuntimeTypeHandle 声明的TypeHandle) 在 System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator 作家,对象图,DataContractResolver dataContractResolver)在 System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator 作家,对象图,DataContractResolver dataContractResolver)在 System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator 作家,对象图,DataContractResolver dataContractResolver)在 System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter 作家,对象图)在 System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(类型 类型、对象值、流 writeStream、HttpContent 内容)在 System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(类型 类型、对象值、流 writeStream、HttpContent 内容、 TransportContext transportContext, CancellationToken cancelToken) --- 从上一个位置结束堆栈跟踪,其中 抛出异常---在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()

【问题讨论】:

    标签: c# serialization asp.net-web-api asp.net-web-api2


    【解决方案1】:

    您的 DTO 类缺少无参数构造函数。见这里:Why XML-Serializable class need a parameterless constructor (很抱歉唤醒这个问题,但我现在也有同样的问题)

    【讨论】:

    • 这对我有用。谢谢。另一个重要注意事项是,您的所有属性都必须具有公共设置器才能进行脱盐
    【解决方案2】:

    如报错所说,无法序列化,考虑添加数据契约属性..

    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; }
    }
    

    更多关于Data Contracts的信息

    【讨论】:

    • 这行得通,但我不明白为什么这是必要的。我清楚地记得不必将数据成员属性添加到简单类型。
    • @JeppeKoefod DataContractSerializer,这是 Web API 默认使用的,是可选的; XmlSerializer 选择退出。
    • asp.net/web-api/overview/formats-and-model-binding/… 声明“默认情况下,所有公共属性和字段都包含在序列化的 JSON 中。要省略属性或字段,请使用 JsonIgnore 属性对其进行装饰。”
    • @JeppeKoefod 您没有序列化为 JSON,而是序列化为 XML。检查您的错误消息。确保在请求中包含适当的 Accept 标头。
    • @KennethK。啊,我明白了。我现在已将其更改为 JSON,并且在没有属性的情况下它可以完美运行。谢谢!
    【解决方案3】:

    从浏览器调用 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 1970-01-01
      • 2017-11-13
      • 2017-03-12
      • 2013-12-10
      相关资源
      最近更新 更多