DataSourceRequest、DataSourceResult 去操作條件因子

 

本範例主要示範 serverFiltering、serverSorting 作法,當中會去特別操作 DataSourceRequest 物件實體。

 

一、Model

Model 的部份為使用北風資料庫的 Product table。

 

二、Controller

HomeController.cs 的內容為

using Kendo.Mvc;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.Mvc;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        private NorthwindEntities db = new NorthwindEntities();
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult GetProducts([DataSourceRequest] DataSourceRequest request)
        {
            //request 物件可視為從前端傳來的 sort、filter 條件因子
            updateARFilter(request.Filters);//去操作 filter 條件因子
            updateARSort(request.Sorts);//去操作 sort 條件因子

            DataSourceResult result = db.Products.ToDataSourceResult(request);

            //將 result 相關數值傳回給前端
            ProductView ProductView = new ProductView();
            ProductView.Items = (IEnumerable<Product>)result.Data;
            ProductView.TotalCount = result.Total;

            return JsonNetResult(ProductView);
        }

        private void updateARFilter(IEnumerable<IFilterDescriptor> iFilters)
        {
            //如果前端傳單一 Filter 條件進來的話,iFilters 集合裡的型態則為 FilterDescriptor
            //如果前端傳複合 Filter 條件進來的話,iFilters 集合裡的型態則為 CompositeFilterDescriptor
            //一個 CompositeFilterDescriptor 包含多個 FilterDescriptor

            //每次前端頁面發出一個 request 就有可能會同時包含兩個 CompositeFilterDescriptor,
            //一個 CompositeFilterDescriptor 為前端 js 已經設定好的條件集合,
            //另一個 CompositeFilterDescriptor 為人工點選所設定的條件集合。

            foreach (var iFilter in iFilters)
            {
                if (iFilter is FilterDescriptor)
                {
                    var filter = (FilterDescriptor)iFilter;

                    //如果有去設定 Discontinued 欄位篩選條件的話,改去篩 UnitPrice 欄位小於 5 的資料出來
                    if (filter.Member == "Discontinued")
                    {
                        filter.Member = "UnitPrice";
                        filter.Operator = FilterOperator.IsLessThan;
                        filter.Value = 5;
                    }
                }
                else if (iFilter is CompositeFilterDescriptor)
                {
                    updateARFilter(((CompositeFilterDescriptor)iFilter).FilterDescriptors);
                }
            }
        }

        private void updateARSort(IList<SortDescriptor> sorts)
        {
            foreach (var sort in sorts)
            {
                //如果有去排序 ReorderLevel 欄位的話,則改去排 ProductID 欄由小到大
                if (sort.Member == "ReorderLevel")
                {
                    sort.Member = "ProductID";
                    sort.SortDirection = ListSortDirection.Ascending;
                }
            }
        }

        private ContentResult JsonNetResult(object model)
        {
            return Content(Newtonsoft.Json.JsonConvert.SerializeObject(model), "application/json", System.Text.Encoding.UTF8);
        }
    }
}

說明:

1、如果前端傳單一 Filter 條件進來的話,iFilters 集合裡的型態則為 FilterDescriptor。

2、如果前端傳複合 Filter 條件進來的話,iFilters 集合裡的型態則為 CompositeFilterDescriptor。

3、一個 CompositeFilterDescriptor 包含多個 FilterDescriptor。

4、sort 的部份,其原理也是跟 filter 大同小異的。

 

三、View

Index.cshtml 的內容為

@{
    ViewBag.Title = "Home Page";
}

<div id="grid"></div>

@section scripts
{
    <script src="https://kendo.cdn.telerik.com/2020.1.406/js/kendo.all.min.js"></script>
    <script src="https://kendo.cdn.telerik.com/2020.1.406/js/kendo.aspnetmvc.min.js"></script>
    <script>
        $(document).ready(init);

        function init() {
            var dataSource = new kendo.data.DataSource({
                type: 'aspnetmvc-ajax',
                transport: {
                    read: {
                        datatype: "json",
                        type: "post",
                        url: "/Home/GetProducts"
                    }
                },
                schema: {
                    data: 'Items',
                    total: 'TotalCount'
                },
                serverPaging: true,
                pageSize: 10,
                serverFiltering: true,
                filter: [
                    { field: 'CategoryID', operator: 'eq', value: 1 },
                    { field: 'SupplierID', operator: 'lte', value: 15 }
                ],
                serverSorting: true,
                sort: {
                    field: "UnitPrice", dir: "desc"
                },
            });

            $("#grid").kendoGrid({
                columns: [
                    { field: "ProductID", width: 120 },
                    { field: "ProductName", width: 120 },
                    { field: "SupplierID", width: 120 },
                    { field: "CategoryID", width: 120 },
                    { field: "QuantityPerUnit", width: 120 },
                    { field: "UnitPrice", width: 120 },
                    { field: "UnitsInStock", width: 120 },
                    { field: "UnitsOnOrder", width: 120 },
                    { field: "ReorderLevel", width: 120 },
                    { field: "Discontinued", width: 120 }
                ],
                dataSource: dataSource,
                pageable: true,
                filterable: true,
                sortable: true
            });
        }
    </script>
}

說明:

注意,當你去操作 DataSourceRequest 物件實體裡面的屬性的話,請記得要 include kendo.aspnetmvc.min.js 檔,

並 kendo.data.DataSource 的 type 屬性要設定為 aspnetmvc-ajax,

否則 DataSourceRequest 物件實體裡面的屬性將為 null。

 

四、FilterDescriptor、SortDescriptor 類別參考

FilterDescriptor 的內容為

namespace Kendo.Mvc
{
    public class FilterDescriptor : FilterDescriptorBase
    {
        public FilterDescriptor();
        public FilterDescriptor(string member, FilterOperator filterOperator, object filterValue);

        public object ConvertedValue { get; }
        public string Member { get; set; }
        public Type MemberType { get; set; }
        public FilterOperator Operator { get; set; }
        public object Value { get; set; }

        public virtual bool Equals(FilterDescriptor other);
        public override bool Equals(object obj);
        public override int GetHashCode();
        protected override Expression CreateFilterExpression(ParameterExpression parameterExpression);
        protected override void Serialize(IDictionary<string, object> json);
    }
}

 

SortDescriptor 的內容為

namespace Kendo.Mvc
{
    public class SortDescriptor : JsonObject, IDescriptor
    {
        public SortDescriptor();
        public SortDescriptor(string member, ListSortDirection order);

        public string Member { get; set; }
        public ListSortDirection SortDirection { get; set; }
        public ClientHandlerDescriptor SortCompare { get; set; }

        public void Deserialize(string source);
        public string Serialize();
        protected override void Serialize(IDictionary<string, object> json);
    }
}