3

I am trying to return JsonResult using MVC controller standard Json(object) method. My object of type Model1 is built by Fluent NHibernate.

Model1 has property of type Model2. In debug mode I see that the environment creates a proxy descendant class of Model2 called Castle.Proxies.Model2Proxy. This is used internally by Fluent Nhibernate, I believe, to satisfy my mappings. And in run time, actual model1.Model2 is of type Castle.Proxies.Model2Proxy.

The problem is that when my Model1 is serialized, Model2 is being serialized too. And the serializer seems to try to serialize all the properties of this object, including those generated by Castle and not needed by me. I would be OK with it if it did not cause an exception. Namely, somewhere inside this object a circular reference presents and the exception is caused by it. Here is the exception text:

System.InvalidOperationException: A circular reference was detected while serializing an object of type 'System.Reflection.RuntimeModule'

I double checked my domain and found no circular references there, so I am blaming Castle. Am I correct? Is Castle really to blame for that? If so, what are my options? How do I tell serializer to ignore Castle properties? Particularly, how do I tell it to serialize the defined type, not the actual one?

I tend to covering my domain models with ViewModels to fight this issue, which is a recommended approach, but I would really love to know another cure, if it exists.

5
  • Does Model2 have a reference to its parent, Model1 by any chance? Commented Jul 12, 2011 at 16:08
  • No, it is definitely Castle proxy object which caused the exception: it contains Type object somewhere down the hierarchy, which has RuntimeModule reference. And the module, naturally, contains a reference to this Type in a collection of all types contained within this module. Commented Jul 12, 2011 at 17:07
  • Does this same error happen if you eagerly load Model2 and then serialize it?
    – Cole W
    Commented Jul 12, 2011 at 22:05
  • @Cole W: I think it should not, as if I load it eagerly, it should become an entity of an expected type Model2, not he proxy. I will verify. I am not sure, however, that I want eager loading in my scenario. Commented Jul 13, 2011 at 8:37
  • @Michael, sJhonny answered what I was getting at.
    – Cole W
    Commented Jul 13, 2011 at 11:44

1 Answer 1

2

in general, it's not good practice to serialize your model entities.
this is because you want to have complete control over what you serialize and send to the client.
when you serialize your model entities, you might be serializing the whole object graph associated with them, which you don't necessarily need / want.
(for example- if you want the user to view just a Model1 entity, you might be sending along also a Model2 entity, along with its Model3 collection etc.)

the standard way to deal with it is using some sort of DTOs, which are adapted to display precisely what you want to display. for example:

public class Model1DTO
{
   public int Id;
   public string Name;
   public string Model2Name;
   //whatever other properties you need to display
}
2
  • Yeah, that's what I came to (see I tend to covering my domain models with ViewModels to fight this issue, which is a recommended approach? You can call it DTO or whatever, still it is a cover). My question is more of a matter of interest for possible future implications and a note on how unpredictable such simple operations as "Jsoning" can be. Commented Jul 13, 2011 at 7:05
  • @Michael: sorry, I must have missed that sentence. Indeed it's the recommended approach, for the reasons I described above. As you say- "unpredictable" is precisely the right word. Since your Domain entities may have complex relationships with each other, some of them may be loaded to memory and some may not, you'd have much better control using 'flattened' objects such as DTOs or ViewModels.
    – J. Ed
    Commented Jul 13, 2011 at 7:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.