C# 序列化住宅建筑类型的对象时检测到循环引用

C# 序列化住宅建筑类型的对象时检测到循环引用,c#,javascript,ajax,visual-studio-2013,C#,Javascript,Ajax,Visual Studio 2013,我在尝试进行AJAX调用时收到以下异常。我不知道这是什么 以下是控制器的代码: public JsonResult getBldgInfo(string type, short stories, int size) { var info = from r in db.ResidentialBuildings where r.type == type && r.stories ==

我在尝试进行AJAX调用时收到以下异常。我不知道这是什么

以下是控制器的代码:

public JsonResult getBldgInfo(string type, short stories, int size)
    {
        var info = from r in db.ResidentialBuildings
                   where r.type == type
                   && r.stories == stories
                   && r.size == size
                   select new { r };
        return Json(info, JsonRequestBehavior.AllowGet);
    }
以下是AJAX调用:

 $("#ResidentialBuildingSize").change(function () {
    infoHead = "infoHead";
    invisible = "invisible";
    type = $("#ResidentialBuildingType").val();
    stories = $("#ResidentialBuildingStories").val();
    size = $("#ResidentialBuildingSize").val();
    console.log(type);
    console.log(stories);
    console.log(size);
    url = "/ResidentialBuilding/getBldgInfo?type=" + type + "&stories=" + stories + "&size=" + size;
    console.log(url);
    $.getJSON(url, function (data) {
        console.log(data);
        $.each(data, function (index, value) {
            $("#titles").empty();
            $("#values").empty();
            $("#titles").append('<h5 class="' + infoHead + '">' + value.r.type + " (" + value.r.stories + ")" + '</h5>');
            $("#titles").append('<p>' + "Stories" + '</p>');
            $("#titles").append('<p>' + "Age" + '</p>');
            $("#titles").append('<p>' + "Size" + '</p>');
            $("#titles").append('<p>' + "Orientation" + '</p>');
            $("#titles").append('<p>' + "Shape" + '</p>');
            $("#titles").append('<p>' + "Floor Height" + '</p>');
            $("#titles").append('<p>' + "Foundation" + '</p>');
            $("#titles").append('<p>' + "Window Percent" + '</p>');
            $("#titles").append('<p>' + "Heating" + '</p>');
            $("#titles").append('<p>' + "Cooling" + '</p>');
            $("#values").append('<h5 class="' + infoHead + ' ' + invisible + '">' + '&nbsp;' + '</h5>');
            $("#values").append('<p><strong>' + value.r.stories + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.age + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.size + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.orientation + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.shape + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.floorht + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.foundation + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.windowpercent + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.heating + '</strong></p>');
            $("#values").append('<p><strong>' + value.r.cooling + '</strong></p>');
        });
    });
});

$("#info").click(function () {
    $("#bldgInfo").slideToggle('2000', 'linear');
});
$(“#ResidentialBuildingSize”).change(函数(){
infoHead=“infoHead”;
不可见=“不可见”;
type=$(“#ResidentialBuildingType”).val();
故事=$(“#住宅建筑故事”).val();
大小=$(“#ResidentialBuildingSize”).val();
console.log(类型);
console.log(故事);
控制台日志(大小);
url=“/ResidentialBuilding/getBldgInfo?type=“+type+”&stories=“+stories+”&size=“+size;
console.log(url);
$.getJSON(url、函数(数据){
控制台日志(数据);
$.each(数据、函数(索引、值){
$(“#标题”).empty();
$(“#值”).empty();
$(“#标题”).append(“+value.r.type+”(“+value.r.stories+”)”+”);
$(“#标题”)。附加(“”+“故事”+”

”); $(“#titles”)。追加(“”+“Age”+”

”); $(“#titles”).append(“”+“Size”+”

”); $(“#titles”)。追加(“”+“方向”+”

”); $(“#titles”).append(“”+“Shape”+”

”); $(“#标题”)。追加(“”+“楼层高度”+”

”); $(“#titles”).append(“”+“Foundation”+”

”); $(“#titles”).append(“”+“窗口百分比”+”

”); $(“#titles”)。追加(“”+“Heating”+”

”); $(“#titles”)。追加(“”+“冷却”+”

”); $(“#值”)。附加(“”+“”+“”); $(“#值”).append(“”+value.r.stories+””); $(“#值”).append(“”+value.r.age+””); $(“#值”).append(“”+value.r.size+””); $(“#值”).append(“”+value.r.orientation+””); $(“#值”).append(“”+value.r.shape+””); $(“#值”).append(“”+value.r.floorht+”

”); $(“β值”)追加((

<强> +Value.R.Fuffe+'/P>'); $(“#值”).append(“”+value.r.windowpercent+”

”); $(“#值”).append(“”+value.r.heating+””); $(“#值”).append(“”+value.r.cooling+””); }); }); }); $(“#信息”)。单击(函数(){ $(“#bldgInfo”).slideToggle('2000','linear'); });
如果我做错了什么,请一定告诉我。当我使用本地数据库时,这段代码就起作用了

更新

下面是ResidentialBuilding模型的代码

namespace BIRDS.Models



public partial class ResidentialBuilding
{
    public ResidentialBuilding()
    {
        this.ResidentialDatas = new HashSet<ResidentialData>();
    }

    public int Id { get; set; }
    public string type { get; set; }
    public short stories { get; set; }
    public int size { get; set; }
    public string age { get; set; }
    public string orientation { get; set; }
    public string shape { get; set; }
    public int floorht { get; set; }
    public string foundation { get; set; }
    public int windowpercent { get; set; }
    public string heating { get; set; }
    public string cooling { get; set; }

    public virtual ICollection<ResidentialData> ResidentialDatas { get; set; }
}
namespace.Models
公共部分类住宅建筑
{
公共住宅建筑()
{
this.ResidentialDatas=new HashSet();
}
公共int Id{get;set;}
公共字符串类型{get;set;}
公共短篇小说{get;set;}
公共整数大小{get;set;}
公共字符串年龄{get;set;}
公共字符串方向{get;set;}
公共字符串形状{get;set;}
public int floorht{get;set;}
公共字符串基础{{GET;set;}
public int windowpercent{get;set;}
公共字符串加热{get;set;}
公共字符串{get;set;}
公共虚拟ICollection ResidentialDatas{get;set;}
}

}

可能您的模型中有导航属性,因此序列化程序会跟踪这些属性,并从链接模型中获取对您的模型的引用,如果没有循环引用检测机制,此过程将无限期地继续

要解决您的问题,请仅选择您感兴趣的属性:

var info = from r in db.ResidentialBuildings
    where r.type == type
    && r.stories == stories
    && r.size == size
    select new { r.stories, r.age, r.size /* etc. */ };

我敢说您的
ResidentialData
类也有一个对
ResidentialBuilding
类的引用。将其序列化为JSON时会发生什么情况,
JavaScriptSerializer
会看到对集合的引用并开始序列化集合。在
ResidentialData
类中,它可以看到对原始
ResidentialBuilding
类的引用,并且它将永远继续进一步序列化。您需要做的是让序列化程序忽略其中任何一个成员—这取决于您的需要

可以通过在项目中添加对
System.Web.Extensions
程序集的引用来实现这一点。从这里,您可以添加对序列化类的引用(
使用System.Web.Script.serialization;

最后,您可以使用该标志,使其不再序列化集合,并且不会抛出循环引用。新类应如下所示:

using System.Web.Script.Serialization;

public partial class ResidentialBuilding
{
    public ResidentialBuilding()
    {
        this.ResidentialDatas = new HashSet<ResidentialData>();
    }

    public int Id { get; set; }
    public string type { get; set; }
    public short stories { get; set; }
    public int size { get; set; }
    public string age { get; set; }
    public string orientation { get; set; }
    public string shape { get; set; }
    public int floorht { get; set; }
    public string foundation { get; set; }
    public int windowpercent { get; set; }
    public string heating { get; set; }
    public string cooling { get; set; }

    [ScriptIgnoreAttribute]
    public virtual ICollection<ResidentialData> ResidentialDatas { get; set; }
}
使用System.Web.Script.Serialization;
公共部分类住宅建筑
{
公共住宅建筑()
{
this.ResidentialDatas=new HashSet();
}
公共int Id{get;set;}
公共字符串类型{get;set;}
公共短篇小说{get;set;}
公共整数大小{get;set;}
公共字符串年龄{get;set;}
公共字符串方向{get;set;}
公共字符串形状{get;set;}
public int floorht{get;set;}
公共字符串基础{{GET;set;}
public int windowpercent{get;set;}
公共字符串加热{get;set;}
公共字符串{get;set;}
[ScriptIgnoreAttribute]
公共虚拟ICollection ResidentialDatas{get;set;}
}

我猜您的:

public virtual ICollection<ResidentialData> ResidentialDatas { get; set; }
公共虚拟ICollection ResidentialDatas{get;set;} 是和实体框架导航属性,并且ResidentialData类具有返回ResidentialBuilding的导航属性

您可以使用DTO来解决这个问题,也许可以使用像AutoMapper这样的库在类型之间映射,根据需要忽略或添加属性。