【问题标题】:C# api gives error "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'."C# api 给出错误“'ObjectContent`1' 类型无法序列化内容类型 'application/xml; charset=utf-8' 的响应正文。”
【发布时间】:2020-02-13 11:18:57
【问题描述】:

我完全遵循了这个tutorial,但是当我运行我的代码时,我收到了这个错误消息。

 <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.DynamicProxies.Player_B392F8ACFF7986B6E577FBE0EA4EC58EB44F1C4138CB96BE272A810004835B21' with data contract name 'Player_B392F8ACFF7986B6E577FBE0EA4EC58EB44F1C4138CB96BE272A810004835B21:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer 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 the serializer.
</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.SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType) 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.<WriteBufferedResponseContentAsync>d__22.MoveNext()
</StackTrace>
</InnerException>
</Error>

我不明白我的代码在哪里失败,因为它与教程相同。

例如,控制器如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using UEFA_APIDataAcces;

namespace UEFA_API.Controllers
{
    [RoutePrefix("api/Match")]
    public class MatchController : ApiController
    {
        [Route("")]
        public IEnumerable<Match> Get()
        {
            using(UEFAEntities entities = new UEFAEntities())
            {
                return entities.Match.ToList();
            }
        }
        [Route("{id:int}")]
        public Match Get(int id)
        {
            using (UEFAEntities entities = new UEFAEntities())
            {
                return entities.Match.FirstOrDefault(e => e.ID == id);
            }
        }
    }

}

我也看到了这个solution,但这对我不起作用。我仍然收到错误消息。

欢迎任何帮助/提示。

提前谢谢你。

【问题讨论】:

  • 你的连接字符串是什么样的?
  • ???我的意思是连接到数据库时的连接字符串。
  • @RahulSharma 抱歉。这是我的连接字符串 'Data Source=MC-IS-LEUK-\SQLEXPRESS;Initial Catalog=UEFA;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework'

标签: c# .net entity-framework api asp.net-web-api


【解决方案1】:

当它知道可以延迟加载数据时,较早的实体框架版本(即 Core 2.1 之前)默认使用代理类作为数据模型。例如,如果你有一个类 Parent 和一个类 Children 的集合,默认情况下,当你通过类似这样的方式加载 Parent 对象时

var parent = entities.Parents.FirstOrDefault(p=>p.Id==pid)

然后 EF 将 - 默认情况下 - 在您第一次尝试引用它们之前不会加载相关的子节点

例如只在你写的地方

var child = parent.Children.Where(c=>c.SomeProperty==true)

是否会发送一个新的 SQL 查询来获取子项。这是通过在运行时为 Parent 对象生成的(对您透明的)代理类​​来实现的,该代理类检测到您想要访问 Children 集合并发出 SQL、进行映射等。

不幸的是,由于各种原因,这些 Proxy 类不适合序列化(如果有的话)。因此,您收到的错误消息。 EF Core 2.1 改变了一些东西,默认情况下延迟加载是关闭的,你必须启用它。但是,如果您使用的是任何早期版本(包括非核心 EF),则默认情况下它处于打开状态。

这也可以解释为什么您创建一个没有外键的新数据库有效,因为 EF 将无法推断与子对象的关系,因此它不会创建代理,这意味着您正在处理的类现在是我们调用 POCO(普通旧 CLR 对象)。但是您正在剥夺自己(和 EF)在关系数据库中拥有相关对象的能力,从长远来看这可能不是一件好事 :)

就更好的解决方案而言,有几个选项可以关闭代理创建,或在序列化之前拉取整个对象图:

var parent = entities.Parents.Include("Children").FirstOrDefault(p=>SomeCondition);

这将一次性加载整个Parent 实体及其所有Children,并避免该问题;但是,这并不总是理想的,因为您实际上可能并非每次都想要Children 实体。

但更好的是,不要直接公开您的 EF 模型,而是使用映射到 DTO(数据传输对象)

我推荐 DTO;使用 DTO 的最大优点是您不需要将 EF 实体暴露给外界,因为例如它们中的某些部分可能与消费者不相关,或者您可能想要对某些孩子进行聚合归还前的收藏等。

有一个很棒的指南here 更深入地讨论了这些主题。

【讨论】:

    【解决方案2】:

    显然这是我在数据库中的外键的问题。我用相同的数据创建了一个新数据库,但没有外键,现在我的应用程序运行良好。

    我希望我也可以帮助其他人回答这个问题。

    【讨论】:

      猜你喜欢
      • 2017-12-13
      • 2015-06-27
      • 2012-12-07
      • 1970-01-01
      • 2017-07-17
      • 1970-01-01
      • 2012-10-07
      • 2013-10-01
      • 2023-03-30
      相关资源
      最近更新 更多