序列化“System.Reflection”类型的对象时检测到循环引用

Posted

技术标签:

【中文标题】序列化“System.Reflection”类型的对象时检测到循环引用【英文标题】:A circular reference was detected while serializing an object of type 'System.Reflection 【发布时间】:2013-04-23 03:59:22 【问题描述】:

我有一个这样的 asp.net MVC 3 控制器操作方法:

public JsonResult GetRecordingRates(int Id)
            
    List<DefaultRateChart> defaultRateCharts = new List<DefaultRateChart>();
    using (IDefaultRateChartManager defaultRateChartManager = new ManagerFactory().GetDefaultRateChartManager()) 
       defaultRateCharts = defaultRateChartManager.GetAll().Where(rc => rc.Currency.Id == Id && (!rc.NumberPrefix.StartsWith("#") || rc.NumberPrefix.StartsWith("Default")) && rc.AccountCredit == "Credit").ToList();
    
    return Json(defaultRateCharts);

我想将此列表发送到 jquery ajax 成功方法,但我收到 500 Internal Server Error

我的 ajax 调用是这样的:

$.ajax(
type: "POST",
dataType: "json",
url: "/Home/GetRecordingRates",
data: 
    Id: $("#hdCurrencyId").val()                 
,
success: function (data) 
        alert(data);
   
); 

在响应选项卡下的 firebug XHR 中,它说:

在序列化“System.Reflection.RuntimeModule”类型的对象时检测到循环引用。

[编辑]

我把action方法改成这样了:

public JsonResult GetRecordingRates(int Id)

    List<DefaultRateChart> defaultRateCharts = new List<DefaultRateChart>();
    using (IDefaultRateChartManager defaultRateChartManager = new ManagerFactory().GetDefaultRateChartManager())
    
        defaultRateCharts = defaultRateChartManager.GetAll().Where(rc => rc.Currency.Id == Id && (!rc.NumberPrefix.StartsWith("#") || rc.NumberPrefix.StartsWith("Default")) && rc.AccountCredit == "Credit").ToList();
    

    return this.Json(
        new
        
            Result = (from obj in defaultRateCharts select new  Id = obj.Id, DialPrefix = obj.NumberPrefix, Rate = obj.PurchaseRates )
        
        , JsonRequestBehavior.AllowGet
     );

我现在没有收到该错误,但我如何才能成功解析 ajax 集合。我将成功更改为关注,但它没有在表中添加行。

success: function (data) 
            var row = $('<tr>');
            for(var i = 0; i < data.length; i++) 
                row.append($('<td>').html(data[i]));
               

            $('#results').append(row);                                      
            jQuery('#RecordingRates').dialog( closeOnEscape: false );
            $(".ui-dialog-titlebar").hide();
            $("#RecordingRates").dialog( dialogClass: 'transparent' );
            $('#RecordingRates').dialog('open');
           
    ); 

在 Firebug Net => XHR=> Json 中,显示以下 JSON:

[Object  Id=

1

,  DialPrefix=

"1"

,  Rate=

2.6

, Object  Id=

3

,  DialPrefix=

"2"

,  Rate=

2.6

, Object  Id=

5

,  DialPrefix=

"7"

,  Rate=

3.5

, 3 more...]


0
    Object  Id=

1

, DialPrefix=

"1"

, Rate=

2.6



1
    Object  Id=

3

, DialPrefix=

"2"

, Rate=

2.6



2
    Object  Id=

5

, DialPrefix=

"7"

, Rate=

3.5



3
    Object  Id=

7

, DialPrefix=

"8"

, Rate=

6



4
    Object  Id=

9

, DialPrefix=

"Default"

, Rate=

5



5
    Object  Id=

15

, DialPrefix=

"Subscription"

, Rate=

15


【问题讨论】:

您是否尝试过硬编码DefaultRateChart 的值并暂时删除using 部分?这样做可能没有意义,但这是找出问题所在的好方法。 @vonv。请查看更新 这是一种新的写作方法还是我是对的,你没有关闭 tr 和 td。当你检查东西时你会得到什么。 @Nick,根本没有添加 Html。我看到使用萤火虫 @DotnetSparrow 这是一个全新的问题。但无论如何,请参阅下面的答案。 【参考方案1】:

当您的 JSON 中的两个或多个对象相互指向时,就会发生这种情况,序列化程序无法将这些对象反映到 JSON 中。您应该使用 Newtonsoft 序列化程序(这里解释了如何操作:Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?)

您可以做几件事。第一个是让配置管理器知道忽略或保留这些引用,如下所示:

        config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;

您可以在对象中注释您不想序列化的属性(因此循环引用将不存在)。使用这样的注释 [JsonIgnore]:

public class Order

    [JsonIgnore]
    public virtual ICollection<OrderLines> OrderLines get; set;  

【讨论】:

感谢您的回答。请参阅已编辑的问题。我需要使用这个集合/json 在表中添加行 在 MVC 3 中并非如此。 好吧,反正我的回答和问题不相符,因为问题已经被编辑过了。【参考方案2】:

如何在 ajax 成功中解析集合。我将成功更改为 以下,但它没有在表中添加行。

您正在返回一个包含以下字段的集合:IdDialPrefixRate,并且您没有使用它们。

var row = $('<tr>');
for(var i = 0; i < data.length; i++) 
    row.append($('<td>').html(data[i]));
   

$('#results').append(row);  

您需要将它们添加到您的循环中:

row.append($('<td>').html(data[i].DialPrefix));
row.append($('<td>').html(data[i].Rate));

【讨论】:

你检查过你真的有数据吗?尝试在控制台中打印 (console.log(data))。 alert 对您没有帮助,请执行 console.log 并在 FF 或 Chrome 中,转到控制台选项卡,如果您收到了一些数据,您应该会看到您的集合(数组)打印出来。在服务器端,您是否检查过 from obj in defaultRateCharts select 产生的结果?先把它放在一个变量中,看看它是否确实有一个值。 我再次更新了问题。抱歉,我知道这是新问题。 您确定results 是您的table 吗?并且它没有被某些元素隐藏或覆盖(z-index)?在循环之后执行alert($('#results').html()) 并查看是否添加了行 - 但它们应该基于您更新的代码(已回答)。

以上是关于序列化“System.Reflection”类型的对象时检测到循环引用的主要内容,如果未能解决你的问题,请参考以下文章

文本框绑定无法将“System.Reflection.RuntimeEventInfo”类型的对象转换为“System.Reflection.MethodInfo”类型

在 Syncfusion.SfDataGrid 中使用分页时出现“System.Reflection.TargetException”类型的异常

反射学习:(System.Reflection)

c#中system.reflection反射的使用

C# 对象与 JSON 字符串的相互转换

序列化类型为XX的对象时检测到循环引用