0

I am using Entity Framework 4.1 code first and ASP.NET MVC 3. I have a Yahoo User Interface (YUI) datatable on my view. I am getting the data (to populate the grid via JSON).

Flow of getting data:

Controller -> Service -> Repository

My context setup:

public DbSet<Category> Categories { get; set; }

Original Repositry:

public IEnumerable<Category> GetAll()
{
   return db.Categories.ToList();
}

Call to this repository method from my service layer:

public IEnumerable<Category> GetAll()
{
   return categoryRepository.GetAll();
}

My action method to retrieve the data and to pass it to the YUI datatable:

public ActionResult JsonCategoriesList()
{
   JsonEncapsulatorDto<Category> data = new JsonEncapsulatorDto<Category>
   {
      DataResultSet = categoryService.GetAll()
   };

   return Json(data, JsonRequestBehavior.AllowGet);
}

JsonEncapsulatorDto code:

public class JsonEncapsulatorDto<T>
{
   public IEnumerable<T> DataResultSet { get; set; }
}

When I use it this way then there is an error in the datatable. I don't know how to view the error. Nothing is displayed. I debugged and I saw that there is a count of 7 in the DataResultSet. So what I did was to change the repository to use some test data and then it worked. What is the difference and how do I get it to display my results?

Repository with test data:

public IEnumerable<Category> GetAll()
{
   List<Category> list = new List<Category>();
   list.Add(new Category { Name = "Brendan" });
   list.Add(new Category { Name = "Charlene" });

   return list;
   //return db.Categories.ToList();
}

Not sure if you guys want to see my setup of the categories datatable:

<div id="dtCategories"></div>

<script type="text/javascript">

   YAHOO.util.Event.onDOMReady(function () {

      var yuiDataSource = YAHOO.util.DataSource;
      var yuiPaginator = YAHOO.widget.Paginator;
      var yuiDataTable = YAHOO.widget.DataTable;
      var dtCategoriesColumnDefs, dtCategoriesDataSource;
      var dtCategoriesConfigs, dtCategoriesDataTable;

      dtCategoriesColumnDefs = [
         { key: 'Name', label: 'Name' }
      ];

      dtCategoriesDataSource = new YAHOO.util.DataSource('@Url.RouteUrl      (Url.AdministrationCategoryJsonCategoriesList())');
      dtCategoriesDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
      dtCategoriesDataSource.responseSchema = {
         resultsList: 'DataResultSet',
         fields: [
            { key: 'Name' }
         ]
      };

      dtCategoriesDataTable = new YAHOO.widget.DataTable('dtCategories', dtCategoriesColumnDefs, dtCategoriesDataSource);

   });

</script>

UPDATE:

Category class:

public class Category
{
   public int Id { get; set; }
   public string Name { get; set; }
   public string Description { get; set; }
   public string MetaKeywords { get; set; }
   public string MetaDescription { get; set; }
   public bool IsActive { get; set; }
   public int? ParentCategoryId { get; set; }
   public virtual Category ParentCategory { get; set; }
   public virtual ICollection<Category> ChildCategories { get; set; }
}

Context class:

public class PbeContext : DbContext
{
   public DbSet<Category> Categories { get; set; }
   public DbSet<Tutorial> Tutorials { get; set; }

   protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
   {
      dbModelBuilder.Entity<Category>()
         .HasOptional(c => c.ParentCategory)
         .WithMany(c => c.ChildCategories)
         .HasForeignKey(p => p.ParentCategoryId);
   }
}

UPDATE 2:

I have another view that that gets a list of Product objects (no circular references) and it populates fine. I debugged to see what the data looks like when it is returned. And this is how the objects looked like in the list:

Categories:

[0] [System.Data.Entity.DynamicProxies.Category_9E42BCEDDE8AA695F718BEBE2224E1D34291FCAF82F801F4995EEB8449479C93]
[1] [System.Data.Entity.DynamicProxies.Category_9E42BCEDDE8AA695F718BEBE2224E1D34291FCAF82F801F4995EEB8449479C93]
[2] [System.Data.Entity.DynamicProxies.Category_9E42BCEDDE8AA695F718BEBE2224E1D34291FCAF82F801F4995EEB8449479C93]

...and so on...

Products:

[0] = {MyProject.Core.DomainObjects.Product}
[1] = {MyProject.Core.DomainObjects.Product}
[2] = {MyProject.Core.DomainObjects.Product}

Can it maybe because of how the data is returned??

Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234

2 Answers2

1

No idea where your error is. Maybe a recursive Category model (usually that's what happens when you don't use view models and try to pass your EF domain models to the view)? In your example you only need to show a table containing one column which is the name of the category. Passing an entire domain IEnumerable<Category> is like a crime. Maybe missing scripts? Maybe this AdministrationCategoryJsonCategoriesList extension method?

Here's a full working example that I wrote for you and that might get you started:

Model:

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string MetaKeywords { get; set; }
    public string MetaDescription { get; set; }
    public bool IsActive { get; set; }
    public int? ParentCategoryId { get; set; }
    public virtual Category ParentCategory { get; set; }
    public virtual ICollection<Category> ChildCategories { get; set; }

    // Obviously this will be in your repository but for the purpose of
    // this demonstration let's hardcode some data
    public static IEnumerable<Category> GetAll()
    {
        List<Category> list = new List<Category>();
        list.Add(new Category { Name = "Brendan" });
        list.Add(new Category { Name = "Charlene" });
        return list;
    }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult JsonCategoriesList()
    {
        var data = Category.GetAll().Select(x => new
        {
            // We select only what we need for our view => the name
            // if you need something else, well, select it here
            Name = x.Name
        }).ToList();
        return Json(new { DataResultSet = data }, JsonRequestBehavior.AllowGet);
    }
}

View:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>YUI Test</title>
    <link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.9.0/build/datatable/assets/skins/sam/datatable.css">
</head>
<body>
    <div id="dtCategories"></div>

    <script src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
    <script src="http://yui.yahooapis.com/2.9.0/build/element/element-min.js"></script>
    <script src="http://yui.yahooapis.com/2.9.0/build/datasource/datasource-min.js"></script>
    <script src="http://yui.yahooapis.com/2.9.0/build/connection/connection-min.js"></script>
    <script src="http://yui.yahooapis.com/2.9.0/build/datatable/datatable-min.js"></script>


    <script type="text/javascript">
        YAHOO.util.Event.onDOMReady(function () {
            var yuiDataSource = YAHOO.util.DataSource;
            var yuiDataTable = YAHOO.widget.DataTable;
            var dtCategoriesColumnDefs, dtCategoriesDataSource;
            var dtCategoriesConfigs, dtCategoriesDataTable;

            dtCategoriesColumnDefs = [{ key: 'Name', label: 'Name'}];

            dtCategoriesDataSource = new YAHOO.util.DataSource('@Url.Action("JsonCategoriesList")');
            dtCategoriesDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
            dtCategoriesDataSource.responseSchema = {
                resultsList: 'DataResultSet',
                fields: [{ key: 'Name'}]
            };

            dtCategoriesDataTable = new YAHOO.widget.DataTable(
                'dtCategories',
                dtCategoriesColumnDefs,
                dtCategoriesDataSource
            );
        });
    </script>
</body>
</html>
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • The reason why I only have Name there is because I just want to get the grid to work. I will add the other later. Thanks, your solution works fine :) – Brendan Vogt Jul 27 '11 at 09:39
  • I don't like to use var, what can I replace it with? – Brendan Vogt Jul 27 '11 at 09:52
  • @Brendan Vogt, which `var` are you referring to? – Darin Dimitrov Jul 27 '11 at 10:05
  • @Brendan Vogt, oh in this I used an anonymous object so you can't replace `var` by anything else. But in a real world application you would use a view model instead of an anonymous object so you could replace `var` (if you want, personally I wouldn't) with `IEnumerable`. – Darin Dimitrov Jul 27 '11 at 11:53
  • This view model will be used just for the grid? I have read that many people are anti var, is this really to be true? Are there maybe performance issues or why do you think people are against using var? – Brendan Vogt Jul 27 '11 at 13:22
  • 1
    @Brendan Vogt, there is absolutely no performance issues with `var`. The compiler infers the actual type so whether you use `var` or the exact type, you will get absolutely the same IL when compiled. I don't know why people are against `var`. Everyone has the right to use whatever he likes. I like `var` and I use it all the time. It makes my code much shorter. Also if I decide to change the return type of a given method, and if this method is called at 100 places in my code I will not have to go to those 100 places and explicitly modify the type of the variable that I am storing the result. – Darin Dimitrov Jul 27 '11 at 13:26
  • @Darin: Agreed. I also like the use of `var` and as for not having to change tons of code when the return type changes, I kind of think that's partly why they invented `var` in the first place! – Tom Chantler Aug 15 '11 at 18:44
0

Please post the Category type definition to see if there is a circular reference, This might help: Json and Circular Reference Exception

Community
  • 1
  • 1
TBohnen.jnr
  • 5,117
  • 1
  • 19
  • 26
  • I can't be sure if it's a circular reference issue or not without the exception (maybe turn off customerrors to see the "yellow screen of death" exception info) but comment out the ParentCategory property in the Category class to test and see if it is – TBohnen.jnr Jul 26 '11 at 09:47
  • I don't get an exception error. It just tells me in the grid "Data error." – Brendan Vogt Jul 26 '11 at 10:09
  • ah okay, I assume then it is actually passing the json, it must then be something to do with the Yahoo datagrid, you can test this by using fiddler to see if the json is returned, you can then also see if it is returning the JSON in the correct structure – TBohnen.jnr Jul 26 '11 at 12:38
  • Ignore that comment. I did it wrong, fixed my mistake and it displays the products in the grid perfectly. Not sure why it is having issues with the Category class. I hope someone else here can answer it. – Brendan Vogt Jul 26 '11 at 12:51