Articles in this section
Category / Section

How can I obtain a WebApiAdaptor enabled aggregate in ASP.NET Web Forms Grid?

2 mins read

Usually, remote data handlers like WebAPIAdaptor, return only the current page records which is the default behavior. So, we can summarize the current page records only in the Grid Summary Footer. The concept behind this adaptor brings the records on demand which means client-end receives only the current page records. Based on the received records only this adaptor summarizes the aggregates and displays them in Grid. If we return whole records to the client-end, concept of the load on demand will be declined. Henceforth, based on the current page records the summary were displayed. 

 

However, we can overcome this behavior using the custom adaptors and custom headers of the DataManager. Using the custom headers, required aggregate fields were shared to the server-end. Based on that selective fields with their records were returned to the client as aggregates along with the Items/count which will display the summary for total records.

 

HTML:

 
<div id="Grid"></div>
 

 

JavaScript:

<script type="text/javascript">
    $(function () {
        $("#Grid").ejGrid({
            dataSource: new ej.DataManager({
                url: "/api/Orders",
                adaptor: new ej.WebApiAdaptor()
            }),
            allowPaging: true,
            showSummary: true,
            summaryRows: [
                {
                    title: "Sum", summaryColumns: [
                      {
                          summaryType: ej.Grid.SummaryType.Sum, displayColumn: "Freight",
                          dataMember: "Freight", format: "{0:C3}"
                      }
                    ]
                }
            ],
            load: "onLoad",
            actionBegin: "onActionBegin",
            columns: [
                    { field: "OrderID", headerText: "Order ID", textAlign: ej.TextAlign.Right },
                    { field: "CustomerID", headerText: "Customer ID" },
                    { field: "EmployeeID", headerText: "Employee ID", textAlign: ej.TextAlign.Right },
                    { field: "Freight", format: "{0:C3}", textAlign: ej.TextAlign.Right },
                    { field: "ShipCity", headerText: "Ship City" }
            ]
        });
    });
</script>

 

Razor:

@(Html.EJ().Grid<object>("Grid")
    .AllowPaging()
    .Datasource(ds =>
    {
        ds.URL("/api/Orders");
        ds.Adaptor(AdaptorType.WebApiAdaptor);
    })
    .ShowSummary()
    .SummaryRow(row =>
    {
        row.Title("Sum")
            .SummaryColumns(col =>
            {
                col.SummaryType(SummaryType.Sum)
                    .Format("{0:C3}")
                    .DisplayColumn("Freight")
                    .DataMember("Freight").Add();
            }).Add();
    })
    .ClientSideEvents(events => {
        events.ActionBegin("onActionBegin");
        events.Load("onLoad");
    })
    .Columns(col =>
    {
        col.Field("OrderID").HeaderText("Order ID").TextAlign(TextAlign.Right).Add();
        col.Field("CustomerID").HeaderText("Customer ID").Add();
        col.Field("EmployeeID").HeaderText("EmployeeID").TextAlign(TextAlign.Right).Add();
        col.Field("Freight").Format("{0:C3}").TextAlign(TextAlign.Right).Add();
        col.Field("ShipCity").HeaderText("Ship City").Add();
    })
)

 

WebForms:

    <ej:Grid id="Grid" runat="server" ShowSummary="true" Allowpaging="true">
        <EditSettings AllowEditing="True" AllowAdding="True" AllowDeleting="True" EditMode="Batch"></EditSettings>
        <ToolbarSettings ShowToolbar="True" ToolbarItems="add,edit,delete,update,cancel"></ToolbarSettings>
        <Columns>
            <ej:Column Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true" TextAlign="Right" />
            <ej:Column Field="CustomerID" HeaderText="Customer ID" />
            <ej:Column Field="EmployeeID" HeaderText="Employee ID" TextAlign="Right" />
            <ej:Column Field="Freight" Format ="{0:C3}" TextAlign="Right"/>
            <ej:Column Field="ShipCity" HeaderText="Ship City"/>
        </Columns>
         <SummaryRows>
                <ej:SummaryRow Title="Sum">
                    <SummaryColumn>
                        <ej:SummaryColumn SummaryType="Sum" Format="{0:C3}" DisplayColumn="Freight" DataMember="Freight" />
                    </SummaryColumn>
                </ej:SummaryRow>
            </SummaryRows>
        <ClientSideEvents Load="onLoad" ActionBegin="onActionBegin"  />
    </ej:Grid>

 

.Net Core

<ej-grid id="Grid" allow-paging="true" load="onLoad" show-summary="true" action-begin="onActionBegin">
    <e-datamanager url="/api/Orders" adaptor="WebApiAdaptor" />
    <e-summary-rows>
        <e-summary-row title="Sum">
            <e-summary-columns>
                <e-summary-column summary-type="Sum" format="{0:C3}" display-column="Freight" datamember="Freight" />
            </e-summary-columns>
        </e-summary-row>
    </e-summary-rows>
    <e-columns>
        <e-column field="OrderID" header-text="Order ID" is-primary-key="true" text-align="Right"></e-column>
        <e-column field="EmployeeID" header-text="Employee ID" text-align="Right"></e-column>
        <e-column field="CustomerID" header-text="Customer ID"></e-column>
        <e-column field="Freight" text-align="Right" format="{0:C3}"></e-column>
        <e-column field="ShipCity" header-text="Ship City">
        </e-column>
    </e-columns>
</ej-grid>

 

Angular2:

<ej-grid id="Grid" #grid [allowPaging]="true" [showSummary]="true" [summaryRows]="summaryrows" [dataSource]="datasrc" (load)="onLoad($event)" (actionBegin)="onActionBegin($event)">
    <e-columns>
        <e-column field="OrderID" headerText="Order ID" isPrimaryKey="true" textAlign="right"></e-column>
        <e-column field="CustomerID" headerText="Customer ID"></e-column>
        <e-column field="EmployeeID" headerText="Employee Name" textAlign="right"></e-column>
        <e-column field="Freight" format="{0:C3}" textAlign="right"></e-column>
        <e-column field="ShipCity" headerText="Ship City"></e-column>
    </e-columns>
</ej-grid>

 

 

TypeScript:

import { Component, OnInit, Input, ElementRef, ViewChild } from '@angular/core';
import { EJComponents } from "ej-angular2/src/ej/core";
 
@Component({
    selector: 'ej-app',
    templateUrl: 'src/grid/grid.component.html',
})
export class GridComponent {
    constructor() {
        this.datasrc = new ej.DataManager({
            url: "/api/Values",
            adaptor: new ej.WebApiAdaptor()
        })
        this.summaryrows = [{
            title: "Sum",
            summaryColumns: [{
                summaryType: ej.Grid.SummaryType.Sum,
                displayColumn: "Freight",
                dataMember: "Freight",
                format: "{0:C3}"
            }]
        }]
    }
    public datasrc: any;
    public summaryrows: any;
}
 

 

Define the Load and ActionBegin events of the Grid along with the customAdaptor. In the Load event, assign the newly extended adaptor to the Grid’s dataSource. In the ActionBegin event, lookup the model.query for aggregates and push them to the custom headers of the dataSource, an ej.DataManager instance.

 
<script>
    var customAdaptor = new ej.WebApiAdaptor().extend({
        processResponse: function (data, ds, query, xhr, request, changes) {
            var resultdata = data, pvt = request && request.ejPvtData;;
            var result = this.base.processResponse.apply(this, [data, ds, query, xhr, request, changes]);
            if (pvt && pvt.aggregates && pvt.aggregates.length) {
                var agg = pvt.aggregates, args = {}, fn, res = {};
                for (var i = 0; i < agg.length; i++) {
                    fn = ej.aggregates[agg[i].type];
                    if (fn)
                        res[agg[i].field + " - " + agg[i].type] = fn(resultdata.aggregate, agg[i].field);
                }
                result.aggregates = res;
            }
            return result;
        }
    });
 
    function onLoad(args) {
        this.model.dataSource.adaptor = new customAdaptor();
    }
 
    function onActionBegin(args) {
        var rows = this.model.summaryRows, scolumns, sCol = [], aggregate = [];
        for (var row = 0, rlen = rows.length; row < rlen; row++) {
            scolumns = rows[row].summaryColumns;
            for (var col = 0, clen = scolumns.length; col < clen; col++) {
                aggregate.push(scolumns[col].dataMember);
            }
        }
        this.model.dataSource.dataSource.headers = []; 
        this.model.dataSource.dataSource.headers.push({ aggregates: JSON.stringify(aggregate) }); 
    }
</script>
 

 

TypeScript:

import { Component, OnInit, Input, ElementRef, ViewChild } from '@angular/core';
import { EJComponents } from "ej-angular2/src/ej/core";
 
@Component({
    selector: 'ej-app',
    templateUrl: 'src/grid/grid.component.html',
})
export class GridComponent {
    constructor() {
        this.customAdaptor = new ej.WebApiAdaptor().extend({
            processResponse: function (data, ds, query, xhr, request, changes) {
                var resultdata = data, pvt = request && request.ejPvtData;
                var result = this.base.processResponse.apply(this, [data, ds, query, xhr, request, changes]);
                if (pvt && pvt.aggregates && pvt.aggregates.length) {
                    var agg = pvt.aggregates, args = {}, fn, res = {};
                    for (var i = 0; i < agg.length; i++) {
                        fn = ej["aggregates"][agg[i].type];
                        if (fn)
                            res[agg[i].field + " - " + agg[i].type] = fn(resultdata.aggregate, agg[i].field);
                    }
                    result.aggregates = res;
                }
                return result;
            }
        });
    }
    public customAdaptor: any;
 
    onLoad(args) {
        args.model.dataSource().adaptor = new this.customAdaptor;
    }
 
    onActionBegin(args) {
        var rows = args.model.summaryRows, scolumns, sCol = [], aggregate = [];
        for (var row = 0, rlen = rows.length; row < rlen; row++) {
            scolumns = rows[row].summaryColumns;
            for (var col = 0, clen = scolumns.length; col < clen; col++) {
                aggregate.push(scolumns[col].dataMember);
            }
        }
        args.model.dataSource().dataSource.headers = [];
        args.model.dataSource().dataSource.headers.push({ aggregates: JSON.stringify(aggregate) });
    }
}
 
 

 

In the server-end, retrieve the pushed aggregated values and deserialize them to List<string>. Use the deserialized object as input for DataOperations for selecting the aggregate columns. Later, return them to the client-end along with the Items/Count wrapped object.

Web API Controller:

    public class OrdersController : ApiController
    {
        NorthwindDataContext db = new NorthwindDataContext();
        public object Get()
        {
            var queryString = HttpContext.Current.Request.QueryString;
            
            string agg = Request.Headers.GetValues("aggregates").ToList()[0];
            int skip = Convert.ToInt32(queryString["$skip"]);
            int take = Convert.ToInt32(queryString["$top"]);
            List<string> aggregates = (List<string>)JsonConvert.DeserializeObject(agg, typeof(List<string>));
 
            IEnumerable<OrdersView> order = db.OrdersViews.ToList();
            DataOperations ds = new DataOperations();
            IEnumerable aggregate = ds.PerformSelect(order, aggregates);
 
            return new { Items = order.Skip(skip).Take(take), Count = order.Count(), aggregate = aggregate };
        }
    }

 

Asp.Net core WebApi controller

    public class OrdersController : ApiController
    {
        NorthwindDataContext db = new NorthwindDataContext();
        public object Get()
        {
            string agg = Request.Headers["aggregates"].ToString();
            int skip = Convert.ToInt32(Request.Query.ToList()[1].Value.ToString());
            int take = Convert.ToInt32(Request.Query.ToList()[2].Value.ToString());            List<string> aggregates = (List<string>)JsonConvert.DeserializeObject(agg, typeof(List<string>));
 
            IEnumerable<OrdersView> order = db.OrdersViews.ToList();
            DataOperations ds = new DataOperations();
            List<string> str = new List<string>();
            IEnumerable aggregate = ds.PerformSelect(order, aggregates);
 
            return new { Items = order.Skip(skip).Take(take), Count = order.Count(), aggregate = aggregate };
        }
    }

 

Note: To avoid the serialization error only, WebApiAdaptor is prevented the default aggregate records returning from server-end. But this KB, proposed a way to generate aggregate for total records. It may lead to the serialization error in the case larger record count.

Figure. Grid with summation of total records for Freight Column.


Note:

A new version of Essential Studio for ASP.NET is available. Versions prior to the release of Essential Studio 2014, Volume 2 will now be referred to as a classic versions.The new ASP.NET suite is powered by Essential Studio for JavaScript providing client-side rendering of HTML 5-JavaScript controls, offering better performance, and better support for touch interactivity. The new version includes all the features of the old version, so migration is easy.

The Classic controls can be used in existing projects; however, if you are starting a new project, we recommend using the latest version of Essential Studio for ASP.NET. Although Syncfusion will continue to support all Classic Versions, we are happy to assist you in migrating to the newest edition.

For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls. If you have any queries or require clarifications, please let us know in the comments section below.

You can also contact us through our support forumsDirect-Trac, or feedback portal. We are always happy to assist you!

 

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please sign in to leave a comment
Access denied
Access denied