0

I do not think I worded the title correctly. I am trying to return results to populate a view. the error message I get in the browser console is "A circular reference was detected while serializing an object of type" all of the documentation says to flatten out the object and exclude properties that are not related to the model. creating a anonymous type is a work around that seems to work for some. I cannot get either to work. if I try something like

var Results = from RS in results
                      select new
                      {
                          BundleId = RS.BundleId
                      };

intellisense does pick it up. Any suggestions?

Controller

{
public class BundleStatusController : Controller
{


    public ActionResult BundleStatus()
    {
        return View();

    }

    [HttpPost]
    public ActionResult BundleStatusRead([DataSourceRequest] DataSourceRequest request)
    {

            var span = DateTime.Today.AddDays(-1);
            DataAccessAdapter adapter = new DataAccessAdapter();
            EntityCollection allBundles = new EntityCollection(new CarrierBundleEntityFactory());
            RelationPredicateBucket filter = new RelationPredicateBucket(CarrierBundleFields.Date <= span);
            adapter.FetchEntityCollection(allBundles, filter);
            var results = allBundles;

            return Json(results.ToDataSourceResult(request));
        }

}

}

View

  @{
ViewBag.Title = "BundleStatusGet";
 }

 <div>
@(Html.Kendo().Grid<ZoomAudits.DAL.EntityClasses.CarrierBundleEntity>()
    .Name("grid")
    .Columns(columns =>
    {
        columns.Bound(c => c.BundleId).Width(140);
        columns.Bound(c => c.CarrierId).Width(190);
        columns.Bound(c => c.Date);
        columns.Bound(c => c.IsSent).Width(110);
    })
    .HtmlAttributes(new { style = "height: 380px;" })
    .Scrollable()
    .Groupable()
    .Sortable()
    .Pageable(pageable => pageable
        .Refresh(true)
        .PageSizes(true)
        .ButtonCount(5))
                .Selectable(selectable => selectable
                .Mode(GridSelectionMode.Multiple)
                .Type(GridSelectionType.Cell))
            //.Events(events => events.Change("onChange").Sync("sync_handler")))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Read(read => read.Action("BundleStatusRead", "BundleStatus"))
                //.Update(update => update.Action("EditingInline_Update", "Grid"))
    )
)

UPDATED CONTROLLER

[HttpPost]
    public ActionResult BundleStatusRead([DataSourceRequest] DataSourceRequest request)
    {

        var span = DateTime.Today.AddDays(-1);
        DataAccessAdapter adapter = new DataAccessAdapter();
        EntityCollection allBundles = new EntityCollection(new CarrierBundleEntityFactory());
        RelationPredicateBucket filter = new RelationPredicateBucket(CarrierBundleFields.Date <= span);
        adapter.FetchEntityCollection(allBundles, filter);


        //...Using AutoMapper
        **Mapper**.CreateMap<UtilityWebSite.Models.CarrierBundleModel, ZoomAudits.DAL.EntityClasses.CarrierBundleEntity>();
        List<UtilityWebSite.Models.CarrierBundleModel> viewModelList = Mapper.Map<List<ZoomAudits.DAL.EntityClasses.CarrierBundleEntity>, List<UtilityWebSite.Models.CarrierBundleModel>>(allBundles);
        return Json(viewModelList.ToDataSourceResult(request));

        //...Not using AutoMapper
        List<UtilityWebSite.Models.CarrierBundleModel> viewBundles = new List<UtilityWebSite.Models.CarrierBundleModel>();
        foreach (ZoomAudits.DAL.EntityClasses.CarrierBundleEntity entityBundle in **EntityCollection**)
        {
            UtilityWebSite.Models.CarrierBundleModel model = new UtilityWebSite.Models.CarrierBundleModel();
            model.BundleID = entityBundle.BundleId;
            model.CarrierId = entityBundle.CarrierId;
            viewBundles.Add(model);
        }
        return Json(viewBundles.ToDataSourceResult(request));

    }

1 Answers1

0

You are facing an issue where your Data Entity object needs to be separated from your Model objects. At first this seems like more work than needed, but as your application grows you will see the benefit in duplicating you classes. Here is how I would go about it.

In your LLBLGEN Domain Class

namespace ZoomAudits.DAL.EntityClasses
{
    public class CarrierBundleEntity
    {
       //....Whatever is generated as your Bundle object from the DB
    }
}

In your Models MVC Folder

namespace MyProjectNamespace.Models
{
    public class CarrierBundleModel
    {
        [Required]
        [Display(Name = "Bundle ID")]
        public int BundleID{get;set;}

        [Required]
        [Display(Name = "Bundle Name")]
        public int BundleName{get;set;}

        //...Other properties you will use in the UI That match the LLBLGen Bundle class  
    }
}

In your Controller Action

[HttpPost]
public ActionResult BundleStatusRead([DataSourceRequest] DataSourceRequest request)
{                   

        var span = DateTime.Today.AddDays(-1);
        DataAccessAdapter adapter = new DataAccessAdapter();
        EntityCollection allBundles = new EntityCollection(new CarrierBundleEntityFactory());
        RelationPredicateBucket filter = new RelationPredicateBucket(CarrierBundleFields.Date <= span);
        adapter.FetchEntityCollection(allBundles, filter);


        //...Using AutoMapper
        Mapper.CreateMap<MyProjectNamespace.Models.CarrierBundleModel, ZoomAudits.DAL.EntityClasses.CarrierBundleEntity>();   
        List<MyProjectNamespace.Models.CarrierBundleModel> viewModelList =Mapper.Map<List<ZoomAudits.DAL.EntityClasses.CarrierBundleEntity>, List<MyProjectNamespace.Models.CarrierBundleModel>>(allBundles);
        return Json(viewModelList.ToDataSourceResult(request));

        //...Not using AutoMapper
        List<MyProjectNamespace.Models.CarrierBundleModel> viewBundles=new List<MyProjectNamespace.Models.CarrierBundleModel>();
        foreach(ZoomAudits.DAL.EntityClasses.CarrierBundleEntity entityBundle in allBundles)
        {
            MyProjectNamespace.Models.CarrierBundleModel model=new MyProjectNamespace.Models.CarrierBundleModel();
            model.BundleID=entityBundle.BundleId;
            model.CarrierId=entityBundle.CarrierId;
            viewBundles.Add(model);
        }
        return Json(viewBundles.ToDataSourceResult(request));

}

In your View

@(Html.Kendo().Grid<MyProject.Models.CarrierBundleModel>()

NOTE: I use AutoMapper which is a great mapping library that you can add to your project and never have to write translations if there is a one to one match between your model and entity data types and names. There are other mapping tools available. I just included to show you an alternative shortcut to translating from DAL entity to Model.

Ross Bush
  • 14,648
  • 2
  • 32
  • 55
  • That is what LLBLGen generates for you to work with it is the ZoomAudits.DAL.EntityClasses.CarrierBundle class – Ross Bush Jun 25 '14 at 16:05
  • It is read only or you do not need to modify it. I showed it just for reference. – Ross Bush Jun 25 '14 at 16:06
  • The name 'Mapper' does not exist in the current context. and at foreach loop the EntityCollection is throwing a error message "is a type but it is used like a variable – user3750212 Jun 25 '14 at 16:33
  • AutoMapper is a third-party library that you would need to download and reference in your project...using AutoMapper;. If you do not want to use it then remove the AutoMapper code. I changed EntityCollection to allBundles it was a typo in my example, sorry :) – Ross Bush Jun 25 '14 at 16:36
  • gotcha, i thought that was two options. sorry really new to this. when i try not using the automapper i get cannot convert System.Datime? to System.DateTime and the same message on my boolean property. I have CarrierId, BundleId, Date, IsSent as my properties – user3750212 Jun 25 '14 at 16:45
  • Then your LLBLGen has picked up that Your CarrierBundles.Date field is optional in the database. You can easily change those values in your model to public DateTime? SomeDateField{get;set} and public bool? SomeBoolField {get;set;}. This allows the SomeDateField to be nullable and the mapping should work. – Ross Bush Jun 25 '14 at 16:48
  • i figured that one out. I appreciate all your help and patience. – user3750212 Jun 25 '14 at 16:56
  • I added the code to my view and then I added this .Model(model => model.Id(p => p.BundleID) because I was getting there is no DataSource error. havent resolved that one yet – user3750212 Jun 25 '14 at 16:57
  • Ok. The above should work with your grid configuration in your original post...Just change out the in the grid's constructor to your new model. I would suggest working through the errors and eventually you will get it. – Ross Bush Jun 25 '14 at 17:23