【问题标题】:Entity Framework relational result Web Api serialization errorEntity Framework 关系结果 Web Api 序列化错误
【发布时间】:2016-01-18 21:42:02
【问题描述】:

我在我的 Wep Api 项目中使用实体框架。我的模型是真实的,如下所示:

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Article> Articles { get; set; }
}
public class Article
{
    public int Id { get; set; }
    public int BlogId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public virtual Blog Blog { get; set; }
}

上下文是这样的:

public class BloggingContext: DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Article> Articles { get; set; }
}

我在我的 asp.net Web Api 控制器中使用它。

public class BlogController: ApiController{
      public IEnumerable<Blog> Get(){

           var context = new BloggingContext();

           return context.Blogs.ToList();
      }
}

我的方法是通过延迟加载获取数据,并序列化为 JSON 数据作为 Web Api 响应。

context.Blogs.ToList() 返回关系数据(我在断点处看到)。

但是 Web Api 结果有错误。

异常消息:

“ObjectContent`1”类型未能序列化响应正文 内容类型'应用程序/json;字符集=utf-8

内部异常:

从“博客”获取价值时出错 'System.Data.Entity.DynamicProxies.Article_D002A1ECE031410435306DCEF780AFF03EBB8BD36DA603662C993107FAEB1917 "ExceptionType": "Newtonsoft.Json.JsonSerializationException

我设置了我的WebApiConfig.cs

 var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
 jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
 config.Formatters.Remove(config.Formatters.XmlFormatter);

【问题讨论】:

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


    【解决方案1】:

    您可以尝试禁用代理生成。至少,如果它不能解决问题,它可能会给你一个更清晰的例外。

    context.Configuration.ProxyCreationEnabled = false;
    

    【讨论】:

    • 此设置清除异常但阻止 Lasy 加载。
    • 您能解释一下为什么在您的示例中需要延迟加载吗?
    • 这是一个处理几乎相同问题的 SO 帖子,该问题似乎与尝试序列化动态代理有关......我也遇到过。 stackoverflow.com/questions/7276507/…
    • 如果我使用延迟加载,我可以列出博客和文章计数(Asp.net 博客 - 6 篇文章)。
    【解决方案2】:

    旧的延迟加载问题!真有趣!

    首先,当您断点并评估一个实体时,它本身会触发延迟加载。实体框架很聪明,但没有帮助。事实上,如果您不进行调试,那么这些相同的属性将为空。

    您有 2 个选项,1. Eager Load 或 2. 如前所述,使用传输对象。但他们为什么会。

    1. 很明显。通过使用context.Blogs.Include(x =&gt; x... etc),您是在告诉实体框架继续加载它们,因为我们需要它。

    2. 为什么使用传输对象有效?好吧,为了将数据传输到新对象中,您必须对旧实体中的所有属性调用 Get 方法,从而触发延迟加载。为此,您可以使用 AutoMapper 等 3rd 方包,但它们可能会导致开销。

    对于 API,我个人建议 Eager 加载。 API 的重点是您作为开发设计端点,您可以限制可以使用和不可以使用的内容。如果你想要延迟加载,那么我建议 MVC 是一个更好的选择。

    【讨论】:

      【解决方案3】:

      尝试在您的控制器中使用数据传输对象。在我的情况下,这解决了问题。BlogModel 是您必须添加以用作 DTO 的新类的名称。它与您的实体类具有相同的属性。

      public IEnumerable<Blog> Get(){
      
             List<BlogModel> listofModels = new List<BlogModel>();
             foreach(var model in whateveristhenameofyourentity.Blogs)
                    {
                           BlogModel blogModel = new BlogModel();
                           blogModel.name = model.name;
                           .
                           .
                           .
                           listofModels.Add(BlogModel);
                    }
               IEnumerable<BlogModel> models = listofModels.AsIEnumerable();
               return models;
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-10
        • 2014-01-09
        • 2020-12-09
        • 1970-01-01
        • 2023-01-25
        • 2015-12-13
        • 1970-01-01
        相关资源
        最近更新 更多