Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind Entity Framework 6 to KendoUI Grid

I have created a test SQL Server database with two tables: WorkItem and WorkItemNote. There is a foreign key between them such that one WorkItem can have many WorkItemNote records. I am trying to display the WorkItems in a Kendo Grid. The Action is returning Json, but nothing is displayed in the grid.
If I create an anonymous object with just the properties I want to display, it works. That indicates that an Entity (WorkItem) that has a relationship (WorkItemNote) cannot be displayed in a Kendo Grid.
Is there any way around this?

My Grid:

<div>
    @(Html.Kendo().Grid<TryToLoadGrid.Models.WorkItem>()
        .Name("grid")
        .HtmlAttributes(new { style = "height:380px;" } )
        .Sortable()
        .Pageable()
        .DataSource(dataSource => dataSource.Ajax().Read(read => read.Action("GetActiveWorkItems", "Home")))
        .Columns(columns =>
            {
                columns.Bound(workItem => workItem.Title);
                columns.Bound(workItem => workItem.Description);
            }
        )
    )
</div>

My action code is:

 public ActionResult GetActiveWorkItems([DataSourceRequest]DataSourceRequest request)
 {
     using (TaskManagerContext context = new TaskManagerContext())
     {
         IQueryable<WorkItem> list = context.WorkItems.Where(x => x.IsActive == true);
         DataSourceResult result = list.ToDataSourceResult(request);
         return Json(result);
     }
 }

As you can see from my Action that I'm not even interested in the WorkItemNotes for the grid.

As proof that it is due to the relationship, I created this second Action which does work and display data:

  public ActionResult GetActiveWorkItems2([DataSourceRequest]DataSourceRequest request)
  {
      using (TaskManagerContext context = new TaskManagerContext())
      {
          List<WorkItem> list = context.WorkItems.Where(x => x.IsActive == true).ToList();
          List<Object> dataObjects = new List<object>();
          foreach (WorkItem workItem in list)
          {
              dataObjects.Add(new { Title = workItem.Title, Description = workItem.Description });
          }

          DataSourceResult result = dataObjects.ToDataSourceResult(request);
          return Json(result);
      }
  }

Is there any way around this?

like image 783
John Mark Howell Avatar asked Oct 14 '14 15:10

John Mark Howell


1 Answers

Personally I think it's a bad practice to use Entity Framework models directly in your UI. You should extract the data you require from your model and place that in a view model. Then you return your list of view models to the client.

public class WorkItemViewModel 
{
    public Int64 ID { get; set; }
    public string Title { get; set }
    public string Desctription { get; set }
}


public ActionResult GetActiveWorkItems2([DataSourceRequest]DataSourceRequest request)
{
    using (TaskManagerContext context = new TaskManagerContext())
    {
        List<WorkItem> list = context.WorkItems.Where(x => x.IsActive == true).ToList();
        List<WorkItemViewModel> dataObjects = new List<WorkItemViewModel>();
        foreach (WorkItem workItem in list)
        {
            dataObjects.Add(new WorkItemViewModel { Title = workItem.Title, Description = workItem.Description });
        }
        return Json(dataObjects.ToDataSourceResult(request));
    }
}


<div>
    @(Html.Kendo().Grid<ViewModelNamespace.WorkItemViewModel>()
        .Name("grid")
        .HtmlAttributes(new { style = "height:380px;" } )
        .Sortable()
        .Pageable()
        .DataSource(dataSource => dataSource.Ajax().Read(read => read.Action("GetActiveWorkItems", "Home")))
        .Columns(columns =>
            {
                columns.Bound(workItem => workItem.ID).Hidden();
                columns.Bound(workItem => workItem.Title);
                columns.Bound(workItem => workItem.Description);
            }
        )
    )
</div>
like image 60
Nic Avatar answered Oct 03 '22 10:10

Nic