这种情况的环境:
我遇到过这样一种情况:包含一个标记为[ScriptIgnore]
的字段会很好。如果没有该属性,该字段将构成循环引用并导致抛出异常。原因与此类似:
public class Foo
{
public int FooId { get; set; }
[ScriptIgnore]
public virtual Collection<Bar> Bars { get; set; }
}
public class Bar
{
public int BarId { get; set; }
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
}
因此,您可以在此处看到,Foo
可以有多个关联的Bars
。 Bar
有一个关联的Foo
。
回到这种情况。我使用include语句在控制器中加载此关联:
.Include( foo => foo.Bars );
没有抛出错误,因为include不受[ScriptIgnore]
注释的影响。在调试时,在检查时正确构造关联。有一个foos
列表,每个foo
都有一个Bars
的关联列表。
现在我要序列化这个构造的列表。我有一个充满数据的视图模型,它看起来像这样:
public class FooView
{
public List<Foo> Foos { get; set; }
public string AsJson()
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(this);
}
}
所以我将这个viewmodel传递给视图并序列化它:
@model FooView
<script type="text/javascript">
var fooViewModel = @( Html.Raw( Model.AsJson() ) );
</script>
不会抛出任何异常,但序列化会正确跳过标有Bars
的字段([ScriptIgnore]
)。在consol.log(fooViewModel)
检查后,很明显有一个Foo
数组,但是Bar
中没有任何关联的Foos
数组。
有没有一种方法可以一次跳过这个[ScriptIgnore]
标签?我意识到,如果它每次跳过,那么序列化器会序列化Foo,看看并看到一个类型Bar的集合,序列化每个Bar,注意Bar有一个关联的Foo,序列化Foo,注意Foo有一个类型Bar的集合.. 。等等。我只是想第一次抓住Bar
的集合。有没有办法实现这个目标?我意识到它将尝试从Bar序列化Foo
,但它将是空的。这一切都是通过热切加载完成的,整个对象图已经构建完毕。
答案 0 :(得分:2)
当我遇到这个时,我最终做的是用Json.NET序列化器替换序列化器,它具有设置,特别是
_jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Json.NET将忽略引用循环中的对象而不是序列化它们。第一次遇到一个对象时,它将像往常一样被序列化,但如果该对象作为自身的子对象遇到,则序列化器将跳过序列化它。
设置信息为http://james.newtonking.com/projects/json/help/index.html?topic=html/SerializingJSON.htm 我使用了http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx 替换序列化程序,然后我将其默认添加到global.asax.cs。
configuration.Formatters.Insert(0, new JsonNetFormatter(serializerSettings));
我意识到这是一种解决方法(实际上并没有处理scriptignore),但是,我从提供的数据库中获得了如此多的循环引用,它似乎是当时最好的解决方案。