ASP Net Core Hierarchy Grid not working

2 Answers 297 Views
Grid
Thomas
Top achievements
Rank 2
Iron
Thomas asked on 03 Feb 2023, 05:31 PM

Hi there,

1st post, so I hope I don't do anything wrong or miss anything.

I have the following models (short version, originally the models do contain a lot more properties)

    

publicclassDevices { public string dealerNo { get; set; } public string outletNumber { get; set; } public List<Application> applications { get; set; }
public string deviceId { get; set; } }

    public class Application
    {
        public int Id { get; set; }
        public string name { get; set; }
        public string version { get; set; }
    }

I would like to have a grid showing all devices, and by unfolding I want to see all applications from this specific device with version and so on.

I checked every available forum topic and hierarchy grid example, but I can't get it to run. The returned result from the controller and database query does contain everything.

This is my view:


@(
Html.Kendo().Grid<Devices>()
                        .Name("grid")
                        .Columns(columns =>
                        {
                            columns.Bound(p => p.dealerNo);
                            columns.Bound(p => p.outletNumber);
                            columns.Bound(p => p.deviceId);
                        })
                        .Groupable()
                        .ColumnMenu()
                        .Sortable()
                        .ClientDetailTemplateId("template")
                        .Scrollable(s => s.Height("auto"))
                        .Filterable()
                        .ToolBar(toolbar =>
                        {
                            toolbar.Search();
                        })
                        .Pageable(p => p
                            .ButtonCount(5)
                            .PageSizes(new[] { 10, 25, 500 })
                            .Refresh(true)
                            .Input(true)
                        )
                        .HtmlAttributes(new { style = "height:600px;" })
                        .DataSource(ds => ds
                            .Ajax()
                            .ServerOperation(false)
                            .Group(groups => groups.Add(p => p.dealerNo))
                            .Events(events => events.Error("error_handler"))
                            .Read(r => r.Action("Devices_Read", "Home").Type(HttpVerbs.Post))
                            .Model(model =>
                            {
                            model.Id(order => order.dealerNo);
                            })
                        )
                    )


<script id="template" type="text/kendo-tmpl">
    @(Html.Kendo().Grid<Application>()
                .Name("grid_#=deviceId#")
                .Columns(columns =>
                {
                    columns.Bound(o => o.name).Width(110);
                    columns.Bound(o => o.version).Width(110);
                    columns.Bound(o => o.availableVersion).Width(110);
                })
                .DataSource(dataSource => dataSource
                    .Ajax()
                    .PageSize(10)
                    .Read(r => r.Action("App_Read", "Home", new { deviceId = "#=deviceId#" }))
                )
                .Pageable()
                .Sortable()
                .ToClientTemplate()
        )
</script>

And the controller:


        public ActionResult App_Read(string id, [DataSourceRequest] DataSourceRequest request)
        {
            // return data
        }

String id on App_Read is always null, and I can't find the error. I need to pass the Devices.deviceId so my query for applications will be filtered for this specific device.

If I use standard read method in the child grid


Action("App_Read", "Home"))

I get all the data, but of course every child grid is showing all applications. 

Please point me to my mistake so I can pass the deviceId string (which is a guid generated by EF Core) to the controller.

 

Thanks,

Thomas

Thomas
Top achievements
Rank 2
Iron
commented on 04 Feb 2023, 09:28 AM

Update:

The grid does indeed post the correct deviceId to the controller

 


Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2 POST https://localhost:12031/Home/App_Read?deviceId=E32BB9B43AE9405F9C238966C803D7DE application/x-www-form-urlencoded;+charset=UTF-8 39
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'SLAStatusChecker.Controllers.HomeController.App_Read (SLAStatusChecker)'
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "App_Read", controller = "Home"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.ActionResult App_Read(System.String, Kendo.Mvc.UI.DataSourceRequest) on controller SLAStatusChecker.Controllers.HomeController (SLAStatusChecker).
But on the controller, the arriving string is always null. Why is the controller not recognizing the string inside the http post from the grid?
Thomas
Top achievements
Rank 2
Iron
commented on 04 Feb 2023, 10:01 AM

Update 2:

I got it to run. The passed deviceId is always null. Through debugging I could see that the deviceId is available in the controller method as

this.Request.QueryString.Value resulting in 

deviceId=E32BB9B43AE9405F9C238966C803D7DE

so, after changing the Controller to 


        public ActionResult App_Read([DataSourceRequest] DataSourceRequest request, string id)
        {
            var input = this.Request.QueryString.Value;
            string output = input.Substring(input.IndexOf('=') + 1);
            var result = _deviceService.GetApps(output);
            var dsResult = result.ToDataSourceResult(request);
            return Json(dsResult);
        }


everything is working.

But I still think that there is something wrong, or do I really need to grab the deviceId like that?

Thanks

Thomas

2 Answers, 1 is accepted

Sort by
0
Accepted
Stoyan
Telerik team
answered on 08 Feb 2023, 12:52 PM

Hi Thomas,

Thank you for sharing your code and for the follow up information that shows the approach you have undertaken to resolve the encountered issue.

Based on the information so far I suspect the deviceId variable isn't serialized to a string by the Controller because it expects a variable with the same name. For example 

        public ActionResult App_Read([DataSourceRequest] DataSourceRequest request, string deviceId)
        {
            ...
        }

should be serialized as expected.

A similar example is shown in the HierarchyController.cs file in the View Source tab of the Grid DetailTemplate Demo.

Please give this suggestion a try and let me know how it works on your side.

Regards,
Stoyan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Thomas
Top achievements
Rank 2
Iron
answered on 09 Feb 2023, 03:55 PM

Hi Stoyan,

now it works like a charme, nice catch, thanks!

 

Best regards

Thomas

Santosh
Top achievements
Rank 1
commented on 16 Aug 2023, 09:05 AM | edited

Hi  Stoyan,

I am also using same pattern to bind nested child grid. In my, case child controller action method being called successesfully but even though records do not display in grid. I am using MVC with Kendo UI version 2023.2.718 and .Net Core 7. Below is Index.cshtml view page code. Please point me what mistake I am doing. Thanks in Advance!

@model IEnumerable<ParentReport>
@using Kendo.Mvc;
@using Kendo.Mvc.UI
@using Kendo.Mvc.Extensions
<!DOCTYPE html>
<html>
<head>

    
<script id="template" type="text/kendo-tmpl">
    @(Html.Kendo().Grid<ChildData>()
            .Name("grid_#=PacID#")
            .Columns(columns =>
            {
                columns.Bound(o => o.DEIGender).Title("Gender").Width(110);
                columns.Bound(o => o.DEICategory).Title("Category").Width(110);
            })
            .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(10)
                .Read(read => read.Action("HierarchyBinding_Child", "DEI", new { pacID = "#=PacID#" }))
            )
            .Pageable()
            .Sortable()
            .ToClientTemplate()
    )
</script>
<script>
    function dataBound() {
        this.expandRow(this.tbody.find("tr.k-master-row").first());
    }
</script>

</head>
<body>
    @(Html.Kendo().Grid(Model)
        .Name("grid")
        .Columns(columns =>
        {
            columns.Bound(o => o.PacID).Title("PacID").Width(110);
            columns.Bound(o => o.PacTitle).Title("PacTitle").Width(110);

        })
        .Sortable()
        .Pageable()
        .Scrollable()
        .ClientDetailTemplateId("template")
        .HtmlAttributes(new { style = "margin-top:10px" })
        .DataSource(dataSource => dataSource
        .Ajax()
        .PageSize(50)
       
        )
        .Events(events => events.DataBound("dataBound"))
        )
</body>
</html>
Stoyan
Telerik team
commented on 18 Aug 2023, 01:19 PM

Hi Santosh,

Usually when such an issue occurs in a single Grid in a large application the cause is that DataSource's type is Ajax. Then the response needs to be extended by the ToDataSourceResult extension method:
    public IActionResult ReadOrders([DataSourceRequest]DataSourceRequest request)
    {
        // Orders can be IQueriable or IEnumerable.
        // The result is a filtered, paged, grouped, and sorted collection.
        var result = orders.ToDataSourceResult(request);

        // response object : { AggregateResults: [], Data: [{},{}], Errors: null, Total: 7 }
        return Json(result);
    }

Otherwise the plain Json response of the Controller won't bind correctly to the DataSource. For more information on this topic you can refer to the DataSource Ajax type section of the Documentation.

I hope the information above is useful.

Tags
Grid
Asked by
Thomas
Top achievements
Rank 2
Iron
Answers by
Stoyan
Telerik team
Thomas
Top achievements
Rank 2
Iron
Share this question
or