title: Circular reference detected while serializing an object - C#, Json
body: <p>I'm trying to serialise an object to return it in Json format in order to create a graph. I am doing this in a class library and returning the string as part of a bigger report. I am getting an error however that says:</p>
  
  <p><code>A circular reference was detected while serializing an object of type 'MyApp.Data.Shop'</code>.</p>
  
  <p>I was following this tutorial and expected a similar Json string to be returned (with more fields of course) - <a href="http://blogs.microsoft.co.il/blogs/pini_dayan/archive/2009/03/12/convert-objects-to-json-in-c-using-javascriptserializer.aspx" rel="nofollow">Tutorial</a></p>
  
  <p>The error is being thrown in this method in my reportengine - </p>
  
  <pre><code>public string GetMonthlyShopSalesJson(List&lt;Sale&gt; sales, MonthlyRequest reportRequest)
  {
      List&lt;MonthlyShopSales&gt; mrs = GetMonthlyShopSales(sales, reportRequest);
  
      JavaScriptSerializer serializer = new JavaScriptSerializer();
      string jsonData = serializer.Serialize(mrs); //Error line
  
      return jsonData;
  }
  </code></pre>
  
  <p>Here is my method for retrieving the shopsales:</p>
  
  <pre><code>public List&lt;MonthlyShopSales&gt; GetMonthlyShopSales(List&lt;Sale&gt; sales, MonthlyRequest reportRequest)
  {
      ModelContainer ctn = new ModelContainer();
      MonthlyDateRange dates = GetComparativeDateRange(reportRequest);
  
      List&lt;MonthlyShopSales&gt; shopSales = (from sale in sales
                                          orderby sale.Shop.Name
                                          group sale by sale.Shop into ret
                                          select new MonthlyShopSales
                                          {
                                              Shop = ret.Key,
                                              TotalNumItemsSoldUSD = ret.Where(it =&gt; it.USDCut.HasValue).Where(it =&gt; it.USDCut != 0).Count(),
                                              TotalNumItemsSoldGBP = ret.Where(it =&gt; it.GBPCut.HasValue).Where(it =&gt; it.GBPCut != 0).Count(),
                                              TotalNumItemsSoldEUR = ret.Where(it =&gt; it.EURCut.HasValue).Where(it =&gt; it.EURCut != 0).Count(),
                                              USDTotalEarnings = PerformCurrencyConversion(ret.Sum(it =&gt; it.USDCut.HasValue ? it.USDCut.Value : 0), 0M, 0M, reportRequest.Currency, dates.BaseStartDate),
                                              GBPTotalEarnings = PerformCurrencyConversion(0M, ret.Sum(it =&gt; it.GBPCut.HasValue ? it.GBPCut.Value : 0), 0M, reportRequest.Currency, dates.BaseStartDate),
                                              EURTotalEarnings = PerformCurrencyConversion(0M, 0M, ret.Sum(it =&gt; it.EURCut.HasValue ? it.EURCut.Value : 0), reportRequest.Currency, dates.BaseStartDate),
                                              TotalNumItemsSoldUSDOverall = sales.Where(it =&gt; it.USDCut.HasValue).Where(it =&gt; it.USDCut != 0).Count(),
                                              TotalNumItemsSoldGBPOverall = sales.Where(it =&gt; it.GBPCut.HasValue).Where(it =&gt; it.GBPCut != 0).Count(),
                                              TotalNumItemsSoldEUROverall = sales.Where(it =&gt; it.EURCut.HasValue).Where(it =&gt; it.EURCut != 0).Count(),
                                              USDTotalEarningsOverall = PerformCurrencyConversion(sales.Sum(it =&gt; it.USDCut.HasValue ? it.USDCut.Value : 0), 0M, 0M, reportRequest.Currency, dates.BaseStartDate),
                                              GBPTotalEarningsOverall = PerformCurrencyConversion(0M, sales.Sum(it =&gt; it.GBPCut.HasValue ? it.GBPCut.Value : 0), 0M, reportRequest.Currency, dates.BaseStartDate),
                                              EURTotalEarningsOverall = PerformCurrencyConversion(0M, 0M, sales.Sum(it =&gt; it.EURCut.HasValue ? it.EURCut.Value : 0), reportRequest.Currency, dates.BaseStartDate)
                                          }).ToList();
      return shopSales;
  }
  </code></pre>
  
  <p>And then here is my class for the MonthlyShopSales:</p>
  
  <pre><code>public class MonthlyShopSales
  {
      public Shop Shop { get; set; }
  
      public int TotalNumItemsSoldUSD { get; set; }
      public int TotalNumItemsSoldGBP { get; set; }
      public int TotalNumItemsSoldEUR { get; set; }
      public int NumberOfItemsSoldPerShop { get { return TotalNumItemsSoldUSD + TotalNumItemsSoldGBP + TotalNumItemsSoldEUR; } }
  
      public decimal USDTotalEarnings { get; set; }
      public decimal GBPTotalEarnings { get; set; }
      public decimal EURTotalEarnings { get; set; }
  
      public decimal OverallEarningsPerShop { get { return USDTotalEarnings + GBPTotalEarnings + EURTotalEarnings; } }
  
      public decimal QtyPercentageOfSales { get { return ((decimal)NumberOfItemsSoldPerShop / (decimal)TotalNumberOfBooksSoldOverall) * 100; } }
      public decimal RevenuePercentageOfSales { get { return (OverallEarningsPerShop / TotalEarningsOverall) * 100; } }
  
      public int TotalNumItemsSoldUSDOverall { get; set; }
      public int TotalNumItemsSoldGBPOverall { get; set; }
      public int TotalNumItemsSoldEUROverall { get; set; }
      public int TotalNumberOfItemsSoldOverall { get { return TotalNumItemsSoldUSDOverall + TotalNumItemsSoldGBPOverall + TotalNumItemsSoldEUROverall; } }
  
      public decimal USDTotalEarningsOverall { get; set; }
      public decimal GBPTotalEarningsOverall { get; set; }
      public decimal EURTotalEarningsOverall { get; set; }
  
      public decimal TotalEarningsOverall { get { return USDTotalEarningsOverall + GBPTotalEarningsOverall + EURTotalEarningsOverall; } }
  }
  </code></pre>
  
  <p>I'm trying to be relatively efficient with the code I'm writing, which is why I'm using the GetMonthlyShopSales method twice - I don't necessarily need all it's values so should I write a separate, more cut down version for my Json string? I am also not sure if this is my problem or not so if someone could help with that it would be great. </p>
  
  <p>Here is the stack trace for anyone who is good at reading that:</p>
  
  <pre><code>[InvalidOperationException: A circular reference was detected while serializing an object of type 'MyApp.Data.Shop'.]
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1549
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +194
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +502
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1424
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +194
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +126
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1380
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +194
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +502
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1424
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +194
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +502
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1424
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +194
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +126
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1380
     System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +194
     System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat) +26
     System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat) +74
     System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj) +6
     MyApp.Business.Reporting.AdvancedReportingEngine.GetMonthlyShopSalesJson(List`1 sales, MonthlyRequest reportRequest) in  C:\Development\MyApp\MyApp.Business\Reporting\AdvancedReportingEngine.cs:75
     MyApp.Business.Reporting.AdvancedReportingEngine.GetMonthlyReport(MonthlyRequest reportRequest) in  C:\Development\MyApp\MyApp.Business\Reporting\AdvancedReportingEngine.cs:61
     MyApp.Web.Areas.User.Controllers.ReportsController.MonthlyDashboardReport(MonthlyRequest reportRequest, FormCollection formValues) in C:\Development\MyApp\MyApp.Web\Areas\User\Controllers\ReportsController.cs:34
     lambda_method(Closure , ControllerBase , Object[] ) +157
     System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
     System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +208
     System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
     System.Web.Mvc.&lt;&gt;c__DisplayClass15.&lt;InvokeActionMethodWithFilters&gt;b__12() +55
     System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +263
     System.Web.Mvc.&lt;&gt;c__DisplayClass17.&lt;InvokeActionMethodWithFilters&gt;b__14() +19
     System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +191
     System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
     System.Web.Mvc.Controller.ExecuteCore() +116
     System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
     System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
     System.Web.Mvc.&lt;&gt;c__DisplayClassb.&lt;BeginProcessRequest&gt;b__5() +37
     System.Web.Mvc.Async.&lt;&gt;c__DisplayClass1.&lt;MakeVoidDelegate&gt;b__0() +21
     System.Web.Mvc.Async.&lt;&gt;c__DisplayClass8`1.&lt;BeginSynchronous&gt;b__7(IAsyncResult _) +12
     System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
     System.Web.Mvc.&lt;&gt;c__DisplayClasse.&lt;EndProcessRequest&gt;b__d() +50
     System.Web.Mvc.SecurityUtil.&lt;GetCallInAppTrustThunk&gt;b__0(Action f) +7
     System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
     System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
     System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
     System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8970061
     System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +184
  </code></pre>
  
  <p>EDIT:</p>
  
  <p>As requested, here is the shop class. It is derived from an EF data model but there's only 3/4 fields in it anyhow:</p>
  
  <pre><code>[MetadataType(typeof(ShopMetadata))]
  public partial class Shop
  {
  
  }
  
  public partial class ShopMetadata
  {
      [DisplayName("Shop Name")]
      [Required(ErrorMessage = "You must specify a Shop name")]
      public string Name { get; set; }
  
      [DisplayName("Region")]
      [Required(ErrorMessage = "You must specify a region")]
      public int Region { get; set; }
  
      [DisplayName("Display Sequence")]
      [Required(ErrorMessage = "You must specify a dispay sequence")]
      public int DisplaySequence { get; set; }
  }
  </code></pre>