This is a migrated thread and some comments may be shown as answers.

Circular reference Exception on Grid + Entity Framework

8 Answers 409 Views
Grid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Julien
Top achievements
Rank 1
Julien asked on 13 Dec 2011, 02:44 PM
Hi,

For my project, I'm using Entity Framework to manage the access to my database, it works great, and make me the possibility to create complex request with a good maintainability.

I'm using for the first time Asp.Net MVC of telerik, and tried to do the most simple things I could: a table, replacing the default generated table in Asp.Net MVC 3, I only need the page-on-scoll datapaging:

@{
     
    Html.Telerik().Grid(Model)
        .Name("Grid")
        .Columns(columns =>
        {
            columns.Bound(o => o.ContactID);
            columns.Bound(o => o.Contact.FirstName);
            columns.Bound(o => o.Contact.LastName);
            columns.Bound(o => o.BirthDate).Format("{0:dd.MM.yyyy}");
        })
        .DataBinding(dataBinding => dataBinding.Ajax().Select("_PageOnScroll", "Grid"))
        .Pageable(paging => paging.Style(GridPagerStyles.Status).PageOnScroll(true))       
        .Render();
         
}



But I directly get this error:
System.InvalidOperationException was unhandled by user code
  Message=A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Employee_34048F4F6A98297F826C798A27640C7383E95E8EA8282EC8A5F738FA0C77CBC3'.
  Source=System.Web.Extensions
  StackTrace:
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat)
       at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj)
       at Telerik.Web.Mvc.UI.ClientSideObjectWriter.AppendCollection(String name, IEnumerable value) in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\ClientSideObjectWriter.cs:line 528
       at Telerik.Web.Mvc.UI.GridPagingSettings.SerializeTo(String key, IClientSideObjectWriter writer) in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\Grid\Settings\GridPagingSettings.cs:line 131
       at Telerik.Web.Mvc.UI.GridClientObjectSerializer`1.Serialize(IClientSideObjectWriter writer) in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\Grid\Serialization\GridClientObjectSerializer.cs:line 52
       at Telerik.Web.Mvc.UI.Grid`1.WriteInitializationScript(TextWriter writer) in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\Grid\Grid.cs:line 567
       at Telerik.Web.Mvc.UI.ScriptRegistrar.WriteScriptStatements(TextWriter writer) in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\ScriptRegistrar\ScriptRegistrar.cs:line 396
       at Telerik.Web.Mvc.UI.ScriptRegistrar.Write(TextWriter writer) in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\ScriptRegistrar\ScriptRegistrar.cs:line 310
       at Telerik.Web.Mvc.UI.ScriptRegistrar.ToHtmlString() in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\ScriptRegistrar\ScriptRegistrar.cs:line 317
       at Telerik.Web.Mvc.UI.ScriptRegistrarBuilder.ToHtmlString() in f:\115\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\UI\ScriptRegistrar\ScriptRegistrarBuilder.cs:line 310
       at Telerik.Web.Mvc.{Dynamic}.ScriptRegistrarBuilder.IHtmlString.ToHtmlString()
       at System.Web.HttpUtility.HtmlEncode(Object value)
       at System.Web.WebPages.WebPageBase.Write(Object value)
       at ASP._Page_Views_Shared__Layout_cshtml.Execute() in d:\Workspace\LocalProjects\MvcTestApplication\MvcTestApplication\Views\Shared\_Layout.cshtml:line 29
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
       at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
       at System.Web.WebPages.WebPageBase.<>c__DisplayClass7.<RenderPageCore>b__6(TextWriter writer)
       at System.Web.WebPages.HelperResult.WriteTo(TextWriter writer)
       at System.Web.WebPages.WebPageBase.Write(HelperResult result)
       at System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body)
       at System.Web.WebPages.WebPageBase.PopContext()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
       at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
       at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
       at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
       at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
  InnerException:

On the 
@(Html.Telerik().ScriptRegistrar().Globalization(true).DefaultGroup(group => group.Combined(true).Compress(true)))</body>

I searched and found this: http://blogs.telerik.com/aspnetmvcteam/posts/10-01-25/resolving-circular-references-when-binding-the-mvc-grid.aspx

But none of the proposal are right for me:
I need ajax databinding due to the pageOnScroll
I need to have navigation properties in both way(one of the good feature of EF I think)
I cannot afford me the time to create ViewModel for each view, I will have something like 80 view, and I've already 50 models.

I sounds like very weird that we do not have any other solutions? In WCF by example, if we have this problem, we can specify our own serializer which supports handling the cyclic references(e.g. http://chabster.blogspot.com/2008/02/wcf-cyclic-references-support.html )

Thank you


8 Answers, 1 is accepted

Sort by
0
Rosen
Telerik team
answered on 14 Dec 2011, 09:11 AM
Hi Julien,

Indeed, beside the mentioned in the blog post ways to workaround this limitation of .NET JavaScriptSerializer, you may also use custom serializer. Please refer to this code library, which demonstrates how to substitute the built-in serializer.

All the best,
Rosen
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the Telerik Extensions for ASP.MET MVC, subscribe to their blog feed now
0
Julien
Top achievements
Rank 1
answered on 14 Dec 2011, 09:41 AM
Thank you for the response,

I've several questions: 
  • How the controller knows that returning "Json" will use the CustomJsonResult.cs? I can't find where it's setted? I saw that it's created in the CustomGridActionResultFactory, but then where this factory is specified?
  • Is there a way to configure the JavaScriptSerializer ton avoid this behavior?
  • When the Circular exception is throwed? When the JavascriptSerializer has to serialize the same object? Why? Because there is this RecursionLimit?
  • It seems the exception is not generated in the "_PageOnScroll" method(I haven't yet defined it, so no circular exception reference), but in the base method. I cannot return a Json here, true? I return a View, so how to use a custom serializer for views?
0
Rosen
Telerik team
answered on 15 Dec 2011, 10:16 AM
Hello Julien,

Straight to your questions:
1. The ActionResultFactory is register through our DI container within Application Start event
2. You are not limited to use the JavaScriptSerializer, thus you may try using WCF DataContract serializer instead and apply the suggestions from the article you have mentioned, or maybe Json.Net for example, as mentioned in this stackoverflow question.
3. As I have mentioned this is an limitation of the JavaScriptSerializer
4. This error is due to the fact that JavaScriptSerializer is used in few other places in our code base. The easiest way to workaround this is by not passing the Model to the grid declaration. 

Regards,
Rosen
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the Telerik Extensions for ASP.MET MVC, subscribe to their blog feed now
0
oliwa
Top achievements
Rank 1
answered on 18 Dec 2011, 05:13 AM
0
Julien
Top achievements
Rank 1
answered on 19 Dec 2011, 07:35 AM
Hi Oliwa,

I already heard once about auto-mapper, but:
If I've an object "User" which has a collection of "Post", with bidirectionnal links, if I want to create a ViewModel for User, but keeping the link TO the Post(and not from the Post to the user), for this viewModel, you know if it is possible?

Because the automapper basically copy references, but in my case, there is one reference in each object of my subject collection which I don't want

Thank you!
0
oliwa
Top achievements
Rank 1
answered on 20 Dec 2011, 03:13 PM
Hey Julien,

I took a slightly different approach.  In my model I have a Training entity that has navigation properties to a Category and a Status.  In my grid I want to display the status name and the category name and allow sorting.  In my grid column bindings I tried doing something like this...

x.Bound(y => y.Status.StatusName).Title("Status");

But when the entire model tree was serialized to JSON the navigation properties caused a circular reference as we both experienced.

I started to go through my model to remove the circular references but I liked having them there.  I didn't want to limit my navigation or hinder my performance in any way which I knew long term I was doing.

So the approach I went with was to create a TrainingViewModel that inherits from my Training model.  This way I didn't have to recreate all of my properties.  I then created 2 denormalized columns on the view model to store the status and category names.  I used AutoMapper to populate my view model with the model data and with AutoMapper I was able to ignore the navigation properties (to avoid circular references) and I was able to apply custom mapping to populate the denormalized properties on my view model.

YMMV.
0
jc
Top achievements
Rank 1
answered on 01 May 2012, 07:05 PM
Hello, 

I am having the same error with EF 4.3 and Telerik Extensions 2012.1.214. I have tried every proposed suggestion I have been able to find in this forum, to no avail. Is there a working solution for this issue that doesn't involve changing the way my application is supposed to behave?

I suggested the extensions for our company and I am in charge of delivering the first pilot. If the pilot works the the extensions will be adopted company wide. However, at this point I think this issue renders the extensions unusable and me in a bad place since it was my recommendation. 

Thank you
0
oliwa
Top achievements
Rank 1
answered on 01 May 2012, 08:19 PM
As far as I know you have 2 options.

1. Change the JSON serializer so you can override how it serializes the data
2. Follow my suggestion here...

http://www.telerik.com/community/forums/aspnet-mvc/grid/circular-reference-exception-on-grid-entity-framework.aspx#1918370

I guess your 3rd option would be to use server side binding.

It's important to note this serialization issue is not a Telerik issue.  It's an ORM to JSON issue.
Tags
Grid
Asked by
Julien
Top achievements
Rank 1
Answers by
Rosen
Telerik team
Julien
Top achievements
Rank 1
oliwa
Top achievements
Rank 1
jc
Top achievements
Rank 1
Share this question
or