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

MVC Grid not populating from datasource when using AJAX

1 Answer 675 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Kenneth
Top achievements
Rank 1
Kenneth asked on 20 Apr 2015, 05:45 PM

Hi All,

I am implementing a project based on one of the Telerik
examples as part of learning KendoUI and MVC.  It is not going well.

By reviewing the browser console on Firefox 37.0.1 and IE 11
I have resolved all JavaScript errors.   All libraries appear to be loading.

The grid populates fine when using server binding but with
Ajax I have the following problem:

If I use this return statement:
      return View("Index", Json(result, "text/html", System.Text.Encoding.UTF8, JsonRequestBehavior.AllowGet));
I get a nicely formatted but empty grid.

If I use this return statement:
     return Json(result, JsonRequestBehavior.AllowGet);
I get my expected data dumped to the screen but no grid.

 

The data being returned by the controller looks like this:

{"Data":[{"EmployeeID":"FITS-0001","FirstName":"John","LastName":"Doe","EmailAddress":"jdoe@acme.com","TelephoneNumber":null,"UserID":"johndoe","JobTitle":null,"EmployeeStatus":null}, {"EmployeeID":"FITS-0002","FirstName":"Jane","LastName":"Doe","EmailAddress":"janedoe@acme.com","TelephoneNumber":null,"UserID":"janedoe","JobTitle":null,"EmployeeStatus":null}],"Total":2,"AggregateResults":null,"Errors":null}

My code is below.  Any pointers would be greatly appreciated. 

Controller -- EmployeeController
 
using System.Linq;
using System.Web.Mvc;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using TestBagWeb.Models;
using TestBagWeb.DAL;
 
namespace TestBagWeb.Controllers
{
    public class EmployeeController : Controller
    {
        public ActionResult Employees_JsonRead([DataSourceRequest]DataSourceRequest request)
        {
            using (TestBagContext employeeData = new TestBagContext())
            {
                IQueryable<Employee> employees = employeeData.Employees;
                DataSourceResult result = employees.ToDataSourceResult(request);
                return View("Index", Json(result, "text/html", System.Text.Encoding.UTF8, JsonRequestBehavior.AllowGet));
                //return Json(result, JsonRequestBehavior.AllowGet);           
            }
        }
    }
}

View -- Employee/Index
 
 
@{
    ViewBag.Title = "Test Bag";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
 
 
@(Html.Kendo().Grid<TestBagWeb.Models.Employee>()
      .Name("employeeGrid")
      .Columns(columns =>
      {
        columns.Bound(c => c.EmployeeID);
        columns.Bound(c => c.FirstName);
        columns.Bound(c => c.LastName);
        columns.Bound(c => c.EmailAddress);
        columns.Bound(c => c.TelephoneNumber);
        columns.Bound(c => c.UserID);
        columns.Bound(c => c.JobTitle);
        columns.Bound(c => c.EmployeeStatus);
        columns.Bound(c => c.FullName);
        columns.Bound(c => c.EmployeeName);
      })
      .Scrollable()
      .Sortable()
      .Pageable()
      .DataSource(dataSource => dataSource
          .Ajax()
              .Read(read => read.Action("Employees_JsonRead", "Employee"))
      )
)

 

Regards


1 Answer, 1 is accepted

Sort by
0
Dimiter Madjarov
Telerik team
answered on 21 Apr 2015, 11:46 AM | edited on 20 Apr 2022, 03:19 PM

Hello Kenneth,

When binding the Grid via Ajax, the read action should only return a JSON converted to dataSourceResult. The complete approach is described on the following documentation page.

Let me know if it helped you to resolve the issue.

Regards,
Dimiter Madjarov
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
Ali
Top achievements
Rank 1
commented on 19 Apr 2022, 07:04 AM

https://docs.telerik.com/kendo-ui/40x

giving error 404 not found

Ivan Danchev
Telerik team
commented on 20 Apr 2022, 03:19 PM

Tamra
Top achievements
Rank 1
commented on 01 Jul 2022, 08:22 PM | edited

I have a very similar problem. The grid populates fine when using server binding but with
Ajax I have the following problem:

When the view first loads, I get a nicely formatted but empty grid.

If I use this return statement:
     return Json(result, JsonRequestBehavior.AllowGet);

No data is in the grid when the page (or view) loads, but if and ONLY IF I click something on the grid, like to sort by a column, then I get my expected data dumped to the screen but no grid. It is on a separate page with white background and black text, and is all the data. It looks just like the OP posted, but with my specific data instead. It looks like it is creating a page/view called Read, from the Products controller, and the URL is:

https://localhost:(number)/Products/Read 

Following the instructions in this video, the grid was populated when I did it the first way. After I changed it to return a json result as instructed, it did not populate the grid, and instead behaves as described above.

https://www.telerik.com/videos/aspnet-mvc/-persistedvalue-kendo-ui-for-asp-net-mvc-grid-value-kendo-ui-for-asp-net-mvc-grid-

Controller & View - that works, grid is populated (but will be very slow, so I want to make the server do the work instead)

Controller

        public ActionResult ProductIndex()
        {
            var products = db.Notifications.Select(p => new Models.Notification
            {
                ID = p.ID,
                NOTIFICATION_TEXT = p.NOTIFICATION_TEXT,
                USER = p.USER,
                ACTIVE_FLAG = p.ACTIVE_FLAG,
                MAINTENANCE_FLAG = p.MAINTENANCE_FLAG,
                DATE_UPDATED = p.DATE_UPDATED
            });

            return View(db.Notifications.ToList());
        }

View

@model IEnumerable<MvcApp.Models.Notification>


@{ ViewBag.Title = "ProductIndex";
                Layout = "~/Views/Shared/_LayoutBare.cshtml"; }
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
    <meta name="viewport" content="width=device-width" />

</head>
<body>
    <br />

    @(Html.Kendo().Grid(Model).Name("Products").Columns(c=>
{
    c.Bound(p => p.ID);
    c.Bound(p => p.NOTIFICATION_TEXT);
    c.Bound(p => p.DATE_UPDATED);
    c.Bound(p => p.ACTIVE_FLAG);
})
        .DataSource(d =>d
        .Ajax()
        .ServerOperation(false) //prevent postback for sort, filter, page, etc
        .PageSize(2)
        )
        .Pageable()
        .Filterable()
        .Sortable()
        .Groupable()
)

    <br />

View - that does not work

@using MvcApp.Models


@{ ViewBag.Title = "ProductIndex";
    Layout = "~/Views/Shared/_LayoutBare.cshtml"; }
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
    <meta name="viewport" content="width=device-width" />

</head>
<body>

    <br />

    <h1>KENDO GRID</h1>

    @(Html.Kendo().Grid<MvcApp.Models.Notification>().Name("Products")

        .Columns(c=>
        {
            c.Bound(p => p.ID);
            c.Bound(p => p.NOTIFICATION_TEXT).Title("NOTE");
            c.Bound(p => p.DATE_UPDATED);
            c.Bound(p => p.ACTIVE_FLAG);
            c.Bound(p => p.USER);
        })
        .DataSource(d =>d
        .Ajax()
        .Read(r => r.Action("Read", "Products"))
        .PageSize(3)
        )
        .Pageable()
        .Filterable()
        .Sortable()
        .Groupable()
)

Controller (named ProductsController)

//[HttpGet] //does not seem to matter if this is here or not
        //public ActionResult Read() //this makes it look for a View named Read, did not work!
        //{
        //    return View();
        //}
        //[HttpPost]//doesn't seem to make any difference
        //[OutputCache(NoStore = true, Duration = 0)] //did not fix it
        public JsonResult Read([DataSourceRequest] DataSourceRequest request)
        {
        //this does SEEM to bring back the data correctly, but why won't the READ action work?
        //the .Read does work when you click to sort a column, but the result is not shown in a view
        //or the grid, but just a blank page with black text and no formatting
        
            DataSourceResult result = db.Notifications.ToDataSourceResult(request,
                model => new Models.Notification
                {
                    ID = model.ID,
                    ACTIVE_FLAG = model.ACTIVE_FLAG,
                    DATE_UPDATED = model.DATE_UPDATED,
                    MAINTENANCE_FLAG = model.MAINTENANCE_FLAG,
                    NOTIFICATION_TEXT = model.NOTIFICATION_TEXT,
                    USER = model.USER
                });

            //return Json(result); //error, need the .AllowGet as shown below
           return Json(result, JsonRequestBehavior.AllowGet);
            //When binding the Grid via Ajax, the read action should only return a JSON converted to dataSourceResult. 
            //it looks like I am doing that, so what else is wrong?

            //return this.Json(result.ToDataSourceResult(request)); //does not work either
        }

Ivan Danchev
Telerik team
commented on 05 Jul 2022, 12:23 PM

Hello Tamra,

I've tested the scenario and the binding of the Grid works as expected at my end. See the attached sample project.

I would suggest checking out the browser's dev tools console for any js exceptions, also verify that the Read action is hit (there is no error 404 not found) and that the action returns data to the client (check the request's response in the browser's dev tools Network tab).

Additionally, I see the view uses a specific Layout:

@{ ViewBag.Title = "ProductIndex";
                Layout = "~/Views/Shared/_LayoutBare.cshtml"; }

Make sure that the required Kendo CSS and js files are loaded in that Layout. The Kendo js files must be loaded after jQuery, and there should be no duplicate references of the Kendo files or the jQuery script.

If you are unable to find the problem, please post the LayoutBare's content, so we can get a better idea how the client-side resources are loaded in it, or modify the sample project I attached so that it demonstrates the problem and attach it back for further review.

Tamra
Top achievements
Rank 1
commented on 05 Jul 2022, 12:51 PM | edited

Thank you for the response. I truly appreciate any help I can get!

I downloaded your sample project and ran it without modifying anything, and this is what I see in the Products index view when it loads and when it is refreshed. I added a breakpoint to the Read method, and it does not get hit.

The second screenshot is what I see when I click to sort a column (in the empty grid in the first screenshot). The breakpoint in the Read method is still not hit.

 

Tamra
Top achievements
Rank 1
commented on 05 Jul 2022, 01:00 PM | edited

This is what my LayoutBare file looks like


<!DOCTYPE html>

<html>
<head>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>CannotPostTitle</title>

 @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")

    @Styles.Render("~/Content/kendo/css")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/kendoui")

</head>
<body>
 <div class="container body-content">
 @RenderBody()
    </div>

 @RenderSection("scripts", required: false)


    @*@{
        Html.ScriptFile("...");
        Html.ScriptFile("...");
    }
    @Html.RenderScripts();*@

</body>
</html>

And this is my App_Start -> BundleConfig


using System.Web;
using System.Web.Optimization;

namespace MvcApp
{
    public class BundleConfig
    {
        // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at https://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));


            bundles.Add(new ScriptBundle("~/bundles/kendoui").Include(
                             "~/Scripts/kendo/2013.3.1119/kendo.web.min.js"
                            ));

            bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
                    "~/Content/kendo/2013.3.1119/kendo.common-bootstrap.min.css",
                    "~/Content/kendo/2013.3.1119/kendo.bootstrap.min.css"));
        }
    }
}

Tamra
Top achievements
Rank 1
commented on 05 Jul 2022, 01:14 PM | edited

I am not sure what these errors mean, but it looks like you are correct, something in the browser is blocking it. Do you know what needs to be done to fix this?

Edit - I am also seeing this error in Firefox. It looks like this is not an issue with the code, but the security policy (which I am not allowed to change). Thank you for your help. 

Content Security Policy: The page’s settings blocked the loading of a resource at https://localhost:44393/favicon.ico (“default-src”).

 

Tamra
Top achievements
Rank 1
commented on 05 Jul 2022, 07:31 PM

In case others have a similar question, here is what finally worked for me. I deleted the file that was causing the page to be blocked. It was just one file, favicon.ico. I did not have to update the browser's security policy.

Then there were other errors. I added kendo.all.min.js and kendo.aspnet.mvc.min.js and the .map files for each of these. Added the 4 files to my project, included them in the project, referenced them with the other .js files.

  updated my Bundle.Config:

bundles.Add(new ScriptBundle("~/bundles/kendoui").Include(
                             "~/Scripts/kendo/2013.3.1119/kendo.web.min.js",
                              "~/Scripts/kendo/2013.3.1119/kendo.all.min.js",
                               "~/Scripts/kendo/2013.3.1119/kendo.aspnetmvc.min.js"
                            ));

The order of things added is apparently very important. Jquery must be before bootstrap. I'm not sure what else. My layout has things added in this order now (I think unchanged)

    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")

    @Styles.Render("~/Content/kendo/css")

    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/kendoui")

And the LAST thing I changed, so the data will populate is to comment out the .Groupable() from my grid. Then it worked. 

It seems like there is a better solution, so that it will still work even if Groupable is enabled on the grid. Maybe the references/versions are not exactly right, but this does work for me now.

Tags
Grid
Asked by
Kenneth
Top achievements
Rank 1
Answers by
Dimiter Madjarov
Telerik team
Share this question
or