Scenario:
I should implement a grid with paging, sorting, filtering, and CRUD on a simple database table.
Database can be accessed only through a WCF service layer.
Paging, sorting, filtering should be done on service layer.
I use RadGrid 2011Q3 and ASP.NET 4.0, IE8, Win7 32bit
I've managed to implement the paging, sorting and filtering using ObjectDataSource with custom paging and some hacking, but there are problems:
- RadGrid calls the ObjectDataSource Select method with maximumRows=-1, no matter what is in PageSize property
(I did a workaround, but this is strange)
- paging works fine until the first attempt to filtering. After the first filtering, the Pager hides, and remains hidden until closing and reopening the page in browser!
- I use System.Linq.Dynamic on WCF service layer to do the filtering, with the filterexpression coming from RadGrid. It's ok for numeric columns, but throws exception on string columns on every type of filtering except of IsNull and IsNotNull filtering. (See attached exception)
- despite setting RadGrid width propery to 1000px, grid spans more wider on screen
ManageXXXs.aspx:
ManageXXXs.aspx.cs:
XXXSource.cs
Server side:
I should implement a grid with paging, sorting, filtering, and CRUD on a simple database table.
Database can be accessed only through a WCF service layer.
Paging, sorting, filtering should be done on service layer.
I use RadGrid 2011Q3 and ASP.NET 4.0, IE8, Win7 32bit
I've managed to implement the paging, sorting and filtering using ObjectDataSource with custom paging and some hacking, but there are problems:
- RadGrid calls the ObjectDataSource Select method with maximumRows=-1, no matter what is in PageSize property
(I did a workaround, but this is strange)
- paging works fine until the first attempt to filtering. After the first filtering, the Pager hides, and remains hidden until closing and reopening the page in browser!
- I use System.Linq.Dynamic on WCF service layer to do the filtering, with the filterexpression coming from RadGrid. It's ok for numeric columns, but throws exception on string columns on every type of filtering except of IsNull and IsNotNull filtering. (See attached exception)
- despite setting RadGrid width propery to 1000px, grid spans more wider on screen
ManageXXXs.aspx:
<%@ Page Title="" Language="C#" MasterPageFile="~/Admin.Master" AutoEventWireup="true" CodeBehind="ManageXXXs.aspx.cs" Inherits="Admin.UI.Pages.ManageXXXs" %><%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %><asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server"></asp:Content><asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server"> <telerik:RadGrid runat="server" ID="grid" Width="1000px" AllowPaging="True" AllowCustomPaging="true" PageSize="20" AllowSorting="true" DataSourceID="objectDataSource" AllowFilteringByColumn="true"> <PagerStyle Mode="NextPrevAndNumeric"/> <MasterTableView DataKeyNames="XXXID" AutoGenerateColumns="false" EditMode="InPlace" ShowHeadersWhenNoRecords="true" NoMasterRecordsText="---" CommandItemDisplay="Top"> <Columns> <telerik:GridEditCommandColumn ButtonType="LinkButton" /> <telerik:GridBoundColumn DataField="XXXID" HeaderText="XXXID" ReadOnly="true" /> <telerik:GridBoundColumn DataField="Isin" HeaderText="Isin" /> <telerik:GridBoundColumn DataField="InstrumentCode" HeaderText="InstrumentCode" /> <telerik:GridBoundColumn DataField="RIC" HeaderText="RIC" /> <telerik:GridBoundColumn DataField="Ticker" HeaderText="Ticker" /> <telerik:GridBoundColumn DataField="DefaultMarket" HeaderText="DefaultMarket" /> <telerik:GridBoundColumn DataField="ForceClosingPrice" HeaderText="ForceClosingPrice" /> <telerik:GridBoundColumn DataField="MarketId" HeaderText="MarketId" /> <telerik:GridBoundColumn DataField="Active" HeaderText="Active" /> <telerik:GridBoundColumn DataField="PriceStep" HeaderText="PriceStep" /> </Columns> </MasterTableView> </telerik:RadGrid> <asp:ObjectDataSource ID="objectDataSource" runat="server" SelectMethod="Select" TypeName="XXXSource" DataObjectTypeName="Admin.Entities.XXX" EnablePaging="true" StartRowIndexParameterName="startRowIndex" MaximumRowsParameterName="maximumRows" SortParameterName="sortColumns" OnObjectCreating="objectDataSource_ObjectCreating" /></asp:Content>ManageXXXs.aspx.cs:
namespace Admin.UI.Pages{ public partial class ManageXXXs : PageBase { XXXClient client = new XXXClient(); protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); grid.VirtualItemCount = this.client.GetXXXCount(new RequestBase<string> { OperatorId = this.OperatorId }).Result; } protected void objectDataSource_ObjectCreating(object sender, System.Web.UI.WebControls.ObjectDataSourceEventArgs e) { e.ObjectInstance = new XXXSource(this.client, this, this.OperatorId, grid.PageSize, grid.MasterTableView.FilterExpression); } }}XXXSource.cs
using System;using System.Collections.Generic;using System.ComponentModel;using Admin.Entites;using Admin.ServiceContracts;namespace Admin.UI.UIFramework{ [DataObject] public class XXXSource { XXXAdminService.XXXAdminClient client; PageBase pageBase; int operatorId; int pageSize; string filter; public XXXSource(XXXAdminService.XXXAdminClient client, PageBase pageBase, int operatorId, int pageSize, string filter) { this.client = client; this.pageBase = pageBase; this.operatorId = operatorId; this.pageSize = pageSize; this.filter = filter; } [DataObjectMethod(DataObjectMethodType.Select)] public List<XXX> Select(int startRowIndex, int maximumRows, string sortColumns) { try { var request = new GetXXXsRequest { OperatorId = operatorId, StartRowIndex = startRowIndex, MaximumRows = pageSize, SortColumns = sortColumns, Filter = filter }; var response = client.GetXXXs(request); if (response.ReturnCode == ReturnCode.OK) { return response.XXXs; } else { pageBase.DisplayMessages(response.ReturnMessages); } } catch (Exception ex) { Logger.Error(ex); pageBase.DisplayMessage("Error!"); } return null; } public int SelectCount() { try { var request = new RequestBase<string> { OperatorId = operatorId, Param = filter }; var response = client.GetXXXCount(request); if (response.ReturnCode == ReturnCode.OK) { return response.Result; } else { pageBase.DisplayMessages(response.ReturnMessages); } } catch (Exception ex) { Logger.Error(ex); pageBase.DisplayMessage("Error!"); } return -1; } }}Server side:
using System;using System.Linq;using System.Linq.Dynamic;using Admin.DAL;using Admin.Entites;using Admin.ServiceContracts;using System.Collections.Generic;namespace Admin.Services{ public class XXXService : IXXX { private void InitLogger() { Logger.InitLogger("AdminServicesLogger"); } public XXXAdminService() : this(true) { } public XXXAdminService(bool initLogger) { if (initLogger) { InitLogger(); } } public GetXXXsResponse GetXXXs(GetXXXsRequest request) { Logger.Info("GetXXXs started"); var response = new GetXXXsResponse(); try { using (FrontContext ctx = new FrontContext()) { //IQueryable<XXX> retList; List<XXX> retList; if (string.IsNullOrWhiteSpace(request.Filter)) retList = ctx.XXXs.ToList(); else retList = ctx.XXXs.Where(request.Filter).ToList(); //IOrderedQueryable<XXX> retList2; IOrderedEnumerable<XXX> retList2; if (!string.IsNullOrWhiteSpace(request.SortColumns)) { var parts = request.SortColumns.Split(' '); if (parts[1] == "ASC") { if (parts[0] == "Active") retList2 = retList.OrderBy(pi => pi.Active); else if (parts[0] == "PriceStep") retList2 = retList.OrderBy(pi => pi.PriceStep); ........... } else if (parts[1] == "DESC") { if (parts[0] == "Active") retList2 = retList.OrderByDescending(pi => pi.Active); else if (parts[0] == "PriceStep") retList2 = retList.OrderByDescending(pi => pi.PriceStep); ............ } } else retList2 = retList.OrderBy(pi => pi.PiacInstrumentumID); response.XXXs = retList2.Skip(request.StartRowIndex).Take(request.MaximumRows).ToList(); response.ReturnCode = ReturnCode.OK; } } catch (Exception ex) { Logger.Error(ex); response.ReturnCode = ReturnCode.Failed; response.AddReturnMessage(new TechnicalError(ex)); } Logger.Info("GetXXXs finished"); return response; } public ResponseBase<int> GetXXXCount(RequestBase<string> request) { Logger.Info("GetXXXCount started"); var response = new ResponseBase<int>(); try { using (XXXContext ctx = new XXXContext()) { if (string.IsNullOrWhiteSpace(request.Param)) response.Result = ctx.XXXs.Count(); else response.Result = ctx.XXXs.Where(request.Param).Count(); response.ReturnCode = ReturnCode.OK; } } catch (Exception ex) { Logger.Error(ex); response.ReturnCode = ReturnCode.Failed; response.AddReturnMessage(new TechnicalError(ex)); } Logger.Info("GetXXXCount finished"); return response; } public AddModifyXXXResponse AddModifyXXX(AddModifyXXXRequest request) { .... } public DeleteXXXResponse DeleteXXX(DeleteXXXRequest request) { .... } }}using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.Entity;using Admin.Entites;namespace Admin.DAL{ public class XXXContext : DbContext { public XXXContext() :base("ConnectionString") { } public DbSet<XXX> XXXs { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<XXX>().ToTable("XXX"); modelBuilder.Entity<XXX>().HasKey(x => new { x.XXXID }); } }}namespace Admin.Entites{ public class XXX { public int XXXID { get; set; } public string Isin { get; set; } public int? InstrumentCode { get; set; } public string RIC { get; set; } public string Ticker { get; set; } public int? DefaultMarket { get; set; } public short ForceClosingPrice { get; set; } public int? MarketId { get; set; } public int? Active { get; set; } public decimal? PriceStep { get; set; } }}