ASP.NET MVC使用Fluent Nhibernate Model生成JSON

3
我正在尝试使用MVC控制器标准的Json(object)方法返回JsonResult。我的Model1类型的对象是通过Fluent NHibernate构建的。
Model1具有类型为Model2的属性。在调试模式下,我看到环境创建了一个Model2的代理后代类,名为Castle.Proxies.Model2Proxy。我认为这是由Fluent Nhibernate内部使用的,以满足我的映射。在运行时,实际的model1.Model2是类型为Castle.Proxies.Model2Proxy。
问题在于,当我的Model1被序列化时,Model2也被序列化了。并且序列化程序似乎尝试序列化此对象的所有属性,包括由Castle生成且我不需要的属性。如果它不引起异常,我会接受它。换句话说,在该对象的某个地方存在循环引用,并且由此引发异常。以下是异常文本:
System.InvalidOperationException: 在序列化类型为'System.Reflection.RuntimeModule'的对象时检测到循环引用
我仔细检查了我的域,并没有发现循环引用,因此我责怪Castle。我是正确的吗?Castle真的应该为此负责吗?如果是,我的选择是什么?如何告诉序列化程序忽略Castle属性?特别是,如何告诉它序列化定义的类型而不是实际的类型?
我倾向于使用ViewModels覆盖我的域模型以解决此问题,这是一种推荐的方法,但我真的很想知道是否存在其他解决方法。

Model2 是否有任何参考其父级 Model1 的引用? - Andrew Whitaker
不,肯定是Castle代理对象引起了异常:它在层次结构中的某个地方包含了Type对象,该对象具有RuntimeModule引用。而且这个模块自然地包含了对此Type的引用,在该模块中包含了所有类型的集合中。 - Michael Sagalovich
如果你急切地加载Model2然后进行序列化,这个同样的错误会发生吗? - Cole W
@Cole W:我认为不应该这样,因为如果我急切地加载它,它应该成为预期类型“Model2”的实体,而不是代理。我会验证一下。但是我不确定在我的情况下是否需要急切加载。 - Michael Sagalovich
@Michael,sJhonny回答了我的问题。 - Cole W
1个回答

2
一般来说,将您的模型实体序列化并不是一个好的实践。
这是因为您希望完全控制序列化和发送给客户端的内容。
当您序列化模型实体时,您可能会序列化与其关联的整个对象图,而这并不一定是您需要或想要的。
(例如- 如果您只想让用户查看一个Model1实体,则可能同时发送一个Model2实体及其Model3集合等。)

处理此问题的标准方法是使用某种DTO,该DTO适用于精确显示您要显示的内容。例如:

public class Model1DTO
{
   public int Id;
   public string Name;
   public string Model2Name;
   //whatever other properties you need to display
}

是的,这就是我要来看的(我倾向于用ViewModels来覆盖我的领域模型以解决这个问题,这是一种推荐的方法)。你可以称它为DTO或其他任何名字,但它仍然是一种遮盖。我的问题更多的是关于可能的未来影响的兴趣和对“Jsoning”这样简单操作的不可预测性的注意事项。 - Michael Sagalovich
@Michael:抱歉,我可能错过了那句话。确实,出于我上面描述的原因,这是推荐的方法。正如你所说,“不可预测”恰恰是正确的词。由于您的域实体之间可能存在复杂的关系,其中一些可能已经加载到内存中,而另一些则没有,因此使用DTO或ViewModel等“扁平化”对象会更好地控制情况。 - J. Ed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接