I am building an application using MVC3, the Razor viewer, the unit of work repository template, and using the EF4.1 Code First to define my data model.
Here's a little background (look at it if you want).
The application itself is an Intranet only.
The two main objects are MenuItem and Department, of which:
- MenuItem can have many branches
- Departments can have many MenuItems
- MenuItem can have MenuItem as parent
This is how I defined my objects
public class MenuItem { public int MenuItemId { get; set; } public string Name { get; set; } public string Url { get; set; } public virtual ICollection<Department> Departments { get; set; } public int? ParentId { get; set; } public virtual MenuItem ParentMenuItem { get; set; } } public class Department { public int DepartmentId { get; set; } public string Name { get; set; } public virtual ICollection<MenuItem> MenuItems { get; set; } }
I am using FluentAPI to define Self Reference Many-to-Many for MenuItem.
The problem I am facing is passing the MenuItem element to the view via JSON. The central issues are that I have a circular link between my objects that the built-in JSON parser cannot handle, and I have lazy loading and creating a proxy that are still on.
I am using the Nuget JSON.net library as my JSON Serializer, as this seems to be a good way to get round reference. Now I'm not sure how to “fix” the problem of proxy generation. The serializer is currently throwing The RelationshipManager object could not be serialized. This type of object cannot be serialized when the RelationshipManager belongs to an entity object that does not implement IEntityWithRelationships. The RelationshipManager object could not be serialized. This type of object cannot be serialized when the RelationshipManager belongs to an entity object that does not implement IEntityWithRelationships.
Can anyone help me with this? If I turn off proxy generation, I'm going to have some fun loading all the MenuItem children, so I am getting away from this. I read quite a lot and there seem to be a lot of different answers, including projecting objects onto another object and serializing this, etc. Etc. Ideally, some way to configure JSON.net to ignore the RelationshipManager?
Update
Here is what I used as a Custom ContractResolver for the JSON.Net serializer. This seems to have sorted out my problem.
public class ContractResolver : DefaultContractResolver { private static readonly IEnumerable<Type> Types = GetEntityTypes(); private static IEnumerable<Type> GetEntityTypes() { var assembly = Assembly.GetAssembly(typeof (IEntity)); var types = assembly.GetTypes().Where(t => String.Equals(t.Namespace, "Namespace", StringComparison.Ordinal)); return types; } protected override List<MemberInfo> GetSerializableMembers(Type objectType) { if (!AllowType(objectType)) return new List<MemberInfo>(); var members = base.GetSerializableMembers(objectType); members.RemoveAll(memberInfo => (IsMemberEntityWrapper(memberInfo))); return members; } private static bool AllowType(Type objectType) { return Types.Contains(objectType) || Types.Contains(objectType.BaseType); } private static bool IsMemberEntityWrapper(MemberInfo memberInfo) { return memberInfo.Name == "_entityWrapper"; } }
IEntity is an interface that is implemented by all the entity objects of my First code.