간단한 JSON 반환을 시도하고 있지만 아래에 다음과 같은 문제가 있습니다.
public JsonResult GetEventData()
{
var data = Event.Find(x => x.ID != 0);
return Json(data);
}
이 질문의 제목에 표시된 예외를 제외하고 HTTP 500을 얻습니다. 나는 또한 시도했다
var data = Event.All().ToList()
같은 문제가 발생했습니다.
이것이 버그입니까, 아니면 제 구현입니까?
답변
JSON 시리얼 라이저가 지원하지 않는 객체 계층 구조에 순환 참조가있는 것 같습니다. 모든 열이 필요합니까? 뷰에서 필요한 속성 만 선택할 수 있습니다.
return Json(new
{
PropertyINeed1 = data.PropertyINeed1,
PropertyINeed2 = data.PropertyINeed2
});
이것은 JSON 객체를 더 가볍고 이해하기 쉽게 만듭니다. 많은 속성이있는 경우 AutoMapper를 사용하여 DTO 객체와 View 객체 를 자동으로 매핑 할 수 있습니다 .
답변
나는 같은 문제를 겪었고 using Newtonsoft.Json;
var list = JsonConvert.SerializeObject(model,
Formatting.None,
new JsonSerializerSettings() {
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
});
return Content(list, "application/json");
답변
복잡한 객체가 결과 json 객체를 실패하게하기 때문에 실제로 발생합니다. 그리고 객체가 매핑되면 자식을 매핑하고 부모를 매핑하여 순환 참조가 발생하기 때문에 실패합니다. Json은 직렬화하는 데 시간이 오래 걸리므로 예외로 인한 문제를 방지합니다.
Entity Framework 매핑도 동일한 동작을 생성하며 솔루션은 원치 않는 모든 속성을 삭제하는 것입니다.
최종 답변을 명시하면 전체 코드는 다음과 같습니다.
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
);
}
Result
속성 내부의 개체를 원하지 않는 경우에도 다음이 될 수 있습니다 .
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
);
}
답변
요약하면 다음과 같은 4 가지 솔루션이 있습니다.
해결 방법 1 : DBContext에 대한 ProxyCreation을 끄고 결국 복원하십시오.
private DBEntities db = new DBEntities();//dbcontext
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;
}
}
해결 방법 2 : Serializer 설정에서 무시하도록 ReferenceLoopHandling을 설정하여 JsonConvert 사용
//using using Newtonsoft.Json;
private DBEntities db = new DBEntities();//dbcontext
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);
}
}
다음 두 가지 솔루션은 동일하지만 강력한 형식이므로 모델을 사용하는 것이 좋습니다.
해결 방법 3 : 필요한 속성 만 포함 된 모델을 반환하십시오.
private DBEntities db = new DBEntities();//dbcontext
public class ProductModel
{
public int Product_ID { get; set;}
public string Product_Name { get; set;}
public double Product_Price { get; set;}
}
public ActionResult Index()
{
try
{
var data = db.Products.Select(p => new ProductModel
{
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);
}
}
해결 방법 4 : 필요한 속성 만 포함하는 새로운 동적 객체를 반환합니다.
private DBEntities db = new DBEntities();//dbcontext
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);
}
}
답변
xml 및 기타 다양한 형식과 마찬가지로 JSON은 트리 기반 직렬화 형식입니다. “트리”는 다음과 같이 객체에 순환 참조가 있으면 사랑하지 않습니다.
root B => child A => parent B => child A => parent B => ...
특정 경로를 따라 탐색을 비활성화하는 방법이 종종 있습니다. 예를 들어 XmlSerializer
부모 속성을로 표시 할 수 있습니다 XmlIgnore
. 해당 json serializer 로 이것이 가능한지 또는 DatabaseColumn
적절한 마커가 있는지 여부 는 알 수 없습니다 ( 매우 직렬화 API를 참조해야하기 때문에 매우 가능성이 낮습니다)
답변
EntityFramework 엔터티를 생성하는 데 사용되는 새로운 DbContext T4 템플릿 때문입니다. 변경 추적을 수행 할 수 있도록이 템플릿은 멋진 POCO를 감싸서 프록시 패턴을 사용합니다. 그러면 JavaScriptSerializer로 직렬화 할 때 문제가 발생합니다.
따라서 두 가지 해결책은 다음과 같습니다.
- 클라이언트에서 필요한 속성을 직렬화하고 반환하면됩니다.
-
컨텍스트의 구성에서 프록시 자동 생성을 설정하여 자동 생성을 끌 수 있습니다
context.Configuration.ProxyCreationEnabled = 거짓;
아래 기사에서 잘 설명했습니다.
http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/
답변
Newtonsoft.Json 사용 : Global.asax Application_Start 메소드에서 다음 행을 추가하십시오.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;