Hi,
I have two tables "Workers" and "Skills" with Many-to-Many relationship. I want to populate a kendoGrid for workers which should allow to filter on Skills. For this I've create a Web API controller which is returning the first row to avoid duplicates because of Many-to-Many:
Return
query.GroupBy(
Function
(t) t.WorkerID).
Select
(
Function
(grp) grp.First()).AsQueryable()
In this scenario how can I return the Total for kendo"DataSource" object to make the ServerPaging work?
Thanks.
12 Answers, 1 is accepted
You should use DataSourceRequest object. Look at this sample: Kendo Grid WebAPI CRUD.
Regards,
Hristo Valyavicharski
Telerik
Thanks Hristo
I've gone through the sample project and it is all ASP.Net MVC whereas I am using Javascript/HTML at client side. I've learnt that to enable server-side paging I need to return "Total" property of "DataSource" object explicitly. In the controller I am returning only row from the query, for example:
query result,
ID Value
1 a
1 b
2 c
3 d
3 e
Out put would be,
ID Value
1 a
2 c
3 d
I want to return total number of rows as 3 and not 5 and the best way to do it.
DataSource configuration:
var
dataSource =
new
kendo.data.DataSource({
type:
"odata"
,
transport: {
read: {
url:
function
(options) {
return
"../api/workersearch"
;
},
dataType:
"json"
}
},
schema: {
model: {
fields: {
WorkerID: { type:
"number"
},
Title: { type:
"string"
},
ForeName: { type:
"string"
},
SurName: { type:
"string"
},
}
},
//--------------------------------------------------------------
//Show the data & count on the grid (otherwise it'll throw the error - "Unable to get __count of undefined or null...."
data:
function
(data) {
return
data;
},
total:
function
(data) {
//NEED TO KNOW HOW TO RETURN TOTAL?
}
//--------------------------------------------------------------
},
pageSize: 20,
serverPaging:
true
,
serverFiltering:
true
,
serverSorting:
true
,
});
Controller method:
Public
Function
GetValues()
As
IQueryable(Of WorkerSearch)
Dim
query
As
New
List(Of WorkerSearch)
Try
Using context
As
ServerApplicationContext = ServerApplicationContext.CreateContext()
Using conn
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
context.DataWorkspace.TempIDData.Details.Name).ConnectionString)
Dim
cmd
As
New
SqlCommand()
cmd.Connection = conn
cmd.CommandText =
"uspWorkerSearch"
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection.Open()
Dim
da
As
SqlDataAdapter =
New
SqlDataAdapter
da.SelectCommand = cmd
Dim
ds
As
DataSet =
New
DataSet
da.Fill(ds)
Dim
table
As
DataTable = ds.Tables(0)
For
Each
row
As
DataRow
In
table.Rows
query.Add(
New
WorkerSearch
With
{
.WorkerID = row.Field(Of
Integer
)(
"WorkerID"
),
.Title = row.Field(Of
String
)(
"Title"
),
.ForeName = row.Field(Of
String
)(
"ForeName"
),
.SurName = row.Field(Of
String
)(
"SurName"
)
})
Next
End
Using
End
Using
Catch
castEx
As
System.InvalidCastException
Throw
Catch
ex
As
Exception
Throw
End
Try
Return
query.GroupBy(
Function
(t) t.WorkerID).
Select
(
Function
(grp) grp.First()).AsQueryable()
End
Function
You can return the Total from the server side by wrapping the data array in another object that have for example the following fields:
- "Data" field - here you can add the previous data
- "Total" field - here you can add the Total count
On the client side you can use the dataSource schema "data" and "total" options as demonstrated below:
data:
function
(data) {
if
(data && data.Data) {
return
data.Data;
}
return
[];
},
total:
function
(data) {
if
(data && data.Total) {
return
data.Total;
}
return
0;
},
Regards,
Vladimir Iliev
Telerik
Hi Vladimir,
I've set server filtering as well and this doesn't work when a filter is applied. It always return total number of rows before filtering the data.
The described behavior appears to be related to the server side code that you are using. Could you please try to modify it in order to get the total count after the filtering is applied to the data?
Regards,
Vladimir Iliev
Telerik
I've tried to follow your suggestions to change server side method but it is not working. If I wrap the query result in an object and return it, I can't use OData query parameters.
Here is the updated method:
<EnableQuery>
Public
Function
Getvalues(id
As
Integer
)
As
Object
'returning an object instead of IQuarable()
Dim
query
As
New
List(Of WorkerSearch)
Dim
userID
As
Short
= SharedClass.GetCurrentUser.UserID
Dim
ownerID
As
Short
= SharedClass.GetSystemOwner.OwnerID
Try
Using context
As
ServerApplicationContext = ServerApplicationContext.CreateContext()
Using conn
As
New
SqlConnection(ConfigurationManager.ConnectionStrings(
context.DataWorkspace.ApplicationData.Details.Name).ConnectionString)
Dim
cmd
As
New
SqlCommand()
cmd.Connection = conn
cmd.CommandText =
"uspWorkerSearch"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(
New
SqlParameter(
"@intSystemOwnerID"
, ownerID))
cmd.Parameters.Add(
New
SqlParameter(
"@intUserID"
, userID))
cmd.Connection.Open()
Dim
da
As
SqlDataAdapter =
New
SqlDataAdapter
da.SelectCommand = cmd
Dim
ds
As
DataSet =
New
DataSet
da.Fill(ds)
Dim
table
As
DataTable = ds.Tables(0)
For
Each
row
As
DataRow
In
table.Rows
query.Add(
New
WorkerSearch
With
{
.WorkerID = row.Field(Of
Integer
)(
"WorkerID"
),
.Title = row.Field(Of
String
)(
"Title"
),
.ForeName = row.Field(Of
String
)(
"ForeName"
),
.SurName = row.Field(Of
String
)(
"SurName"
)
})
Next
End
Using
End
Using
Catch
castEx
As
System.InvalidCastException
Throw
Catch
ex
As
Exception
Throw
End
Try
'Wraping up query in an array
Dim
myArr()
As
WorkerSearch = query.GroupBy(
Function
(t) t.WorkerID).
Select
(
Function
(grp) grp.First()).ToArray()
'Returning the object with data and total
Return
New
With
{
.Data = myArr,
.Total = myArr.Length}
End
Function
Can you please guide me to the right direction.
Thanks.
In current case handling the request on the server side falls outside the scope of our support service as it covers the build-in functionality of the controls only. That why currently I could only suggest to make sure the query is executed before getting the tolal count.
Another option would be to check the "Kendo.DynamicLinq" project which implements server paging (including total count), filtering, sorting and aggregating and you can use it to request the data in your case.
Regards,
Vladimir Iliev
Telerik
Hi,
another solution would be to write an odata function that returns the correct number of rows and call this via an ajax call from the total function of the datasource?
When server operations (including paging) is used the server side should return back to the client side number of records that are equal or less than the selected page size. If filtering is applied you should first filter the records, then get the total count and finally get only the records for current page and page size.
Regards,
Vladimir Iliev
Telerik
As I mention in my previous replies modifying the custom server code that you are using falls outside the scope of this support service and depends entirely on you.
Regards,
Vladimir Iliev
Telerik