zoukankan      html  css  js  c++  java
  • Json循环引用问题

    I am trying to do a simple JSON return but I am having issues I have the following below.

    public JsonResult GetEventData()
    {
        var data = Event.Find(x => x.ID != 0);
        return Json(data);
    }
    

    I get a HTTP 500 with the exception as shown in the title of this question. I also tried

    var data = Event.All().ToList()
    

    That gave the same problem.

    Is this a bug or my implementation?

    It seems that there are circular references in your object hierarchy which is not supported by the JSON serializer. Do you need all the columns? You could pick up only the properties you need in the view:

    return Json(new 
    {  
        PropertyINeed1 = data.PropertyINeed1,
        PropertyINeed2 = data.PropertyINeed2
    });
    

    This will make your JSON object lighter and easier to understand. If you have many properties, AutoMapper could be used to automatically map between DTO objects and View objects.

    I had the same problem and solved by using Newtonsoft.Json;

    var list = JsonConvert.SerializeObject(model,
        Formatting.None,
        new JsonSerializerSettings() {
            ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    });
    
    return Content(list, "application/json");




    This actually happens because the complex objects are what makes the resulting json object fails. And it fails because when the object is mapped it maps the children, which maps their parents, making a circular reference to occur. Json would take infinite time to serialize it, so it prevents the problem with the exception.

    Entity Framework mapping also produces the same behavior, and the solution is to discard all unwanted properties.

    Just expliciting the final answer, the whole code would be:

    public JsonResult getJson()
    {
        DataContext db = new DataContext ();
    
        return this.Json(
               new {
                    Result = (from obj in db.Things select new {Id = obj.Id, Name = obj.Name})
                   }
               , JsonRequestBehavior.AllowGet
               );
    }
    

    It could also be the following in case you don't want the objects inside a Result property:

    public JsonResult getJson()
    {
        DataContext db = new DataContext ();
    
        return this.Json(
               (from obj in db.Things select new {Id = obj.Id, Name = obj.Name})
               , JsonRequestBehavior.AllowGet
               );
    }


    To sum things up, there are 3 solutions to this:

        private DBEntities db = new DBEntities();//dbcontext
    
        //Solution 1: turn off ProxyCreation for the DBContext and restore it in the end 
        public ActionResult Index()
        {
            bool proxyCreation = db.Configuration.ProxyCreationEnabled;
            try
            {
                //set ProxyCreation to false
                db.Configuration.ProxyCreationEnabled = false;
    
                var data = db.Products.ToList();
    
                return Json(data, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return Json(ex.Message);
            }
            finally
            {
                //restore ProxyCreation to its original state
                db.Configuration.ProxyCreationEnabled = proxyCreation;
            }
        }
    
        //Solution 2: Using JsonConvert by Setting ReferenceLoopHandling to ignore on the serializer settings. 
        //using using Newtonsoft.Json;
        public ActionResult Index()
        {
            try
            {
                var data = db.Products.ToList();
    
                JsonSerializerSettings jss = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
                var result = JsonConvert.SerializeObject(data, Formatting.Indented, jss);
    
                return Json(result, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return Json(ex.Message);
            }
        }
    
        //Solution 3: return a new dynamic object which includes only the needed properties.
        public ActionResult Index()
        {
            try
            {
                var data = db.Products.Select(p => new
                                                    {
                                                        Product_ID = p.Product_ID,
                                                        Product_Name = p.Product_Name,
                                                        Product_Price = p.Product_Price
                                                    }).ToList();
    
                return Json(data, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return Json(ex.Message);
            }
        }





    ts because of the new DbContext T4 template that is used for generating the EntityFramework entities. In order to be able to perform the change tracking, this templates uses the Proxy pattern, by wrapping your nice POCOs with them. This then causes the issues when serializing with the JavaScriptSerializer.

    So then the 2 solutions are:

    1. Either you just serialize and return the properties you need on the client
    2. You may switch off the automatic generation of proxies by setting it on the context's configuration

      context.Configuration.ProxyCreationEnabled = false;

    Very well explained in the below article.

    http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/

  • 相关阅读:
    layui弹出层处理(获取、操作弹出层数据等)
    Unity3D判断鼠标向右或向左滑动,响应不同的事件
    (转载)李剑英的CSLight入门指南结合NGUI热更新
    Unity3D研究院之LZMA压缩文件与解压文件
    CSLight研究院之学习笔记结合NGUI(一)
    《暗黑世界GM管理后台系统》部署+功能说明文档
    Firefly卡牌手游《暗黑世界V1.5》服务器端源码+GM管理后台源码
    电信SDK Pay函数里面System.out.print 无输出消息
    WP8:在Unity中使用OpenXLive
    WP8:Unity3D之间的值传递
  • 原文地址:https://www.cnblogs.com/Alex80/p/9050374.html
Copyright © 2011-2022 走看看