在之前的一篇文章中,我们讨论了如何添加一大堆的超赞的功能到一个标准的HTML表,并把它转换成一个“grid”表格。今天我想要做的事情是向你展示如何将这些功能转到服务器。
通过使用服务器做大量的“苦力活儿”,我们可以向我们的最终用户提供更加平顺的用户体验。什么苦力活要交给服务器呢?假设你有一百万行的数据集,这些数据要是发送到客户端,然后再进行排序/分页/过滤,那会是相当可观的一堆流量。但是如果我们要求服务器在发送数据到客户端之前执行排序/分页/过滤,我们可以迅速的减少客户端的开销。
服务器
关于数据,我使用Chinook数据库。它速度快,容易设置,同时可以给我的例子提供很好的数据。我在例子中使用到了ASP.NET MVC3,并且我们只实现排序和过滤。
public JsonResult GetAlbumList() { int pageSize = Request.Params["paging[pageSize]"] != null ? Convert.ToInt32(Request.Params["paging[pageSize]"]) : 0; int pageIndex = Request.Params["paging[pageIndex]"] != null ? Convert.ToInt32(Request.Params["paging[pageIndex]"]) : 0; string sortColumn = Request.Params["sorting[0][dataKey]"]; string sortDirection = Request.Params["sorting[0][sortDirection]"]; if (string.IsNullOrEmpty(sortColumn)) sortColumn = String.Empty; if (string.IsNullOrEmpty(sortDirection)) sortDirection = String.Empty; using (var entity = new ChinookEntities()) { var allAlbums = from al in entity.Albums join ar in entity.Artists on al.ArtistId equals ar.ArtistId select new AlbumResult() { AlbumName = al.Title, ArtistName = ar.Name }; var totalRowCount = allAlbums.Count(); if (pageSize == 0) pageSize = totalRowCount; if (sortColumn.ToLower() != "album") allAlbums = sortDirection.ToLower() == "descending" ? allAlbums.OrderByDescending(p => p.ArtistName).Skip(pageSize*pageIndex).Take(pageSize) : allAlbums.OrderBy(p => p.ArtistName).Skip(pageSize*pageIndex).Take(pageSize); else allAlbums = sortDirection.ToLower() == "descending" ? allAlbums.OrderByDescending(p => p.AlbumName).Skip(pageSize*pageIndex).Take(pageSize) : allAlbums.OrderBy(p => p.AlbumName).Skip(pageSize*pageIndex).Take(pageSize); var result = new WijmoGridResult { Items = allAlbums.ToList(), TotalRowCount = totalRowCount }; return Json(result, JsonRequestBehavior.AllowGet); } }
让我们一行一行的看一看这些代码都作了些什么,因为他确实做了很多事情!最初的六行抽取了Wijmo需要发送的Request参数。因为很有可能这些值为空,一点点的参数检查逻辑是必须的。
从using表达式开始,我们使用Entity Framework打开一个到我们数据库的链接。我们使用延迟加载的想法对创建结构化查询,因此和SQL服务器的交互只有一次。第一次查询创建对数据库中所有相册的查询。获取所有行的个数是必须的。Wijmo会使用这个结果判断分页需求。
关于排序,你也许已经被巨复杂的IF..ELSE表达式折磨得疲惫不堪。所有这些逻辑仅仅是为了判断我们要基于哪一列进行排序以及按照何种方式(升序或者降序)进行排列,同时应用LINQ过滤。这些调用同时也使用了Skip()以及Take()技术进行分页。
最后,你可能注意到了我还没有给出AlbumReult以及WijmoGridResult的定义。以下是这些类的代码:
public class AlbumResult { public string AlbumName { get; set; } public string ArtistName { get; set; } } public class WijmoGridResult { public List Items { get; set; } public int TotalRowCount { get; set; } }
客户端
现在服务器端已经配置好了,我们需要改变一点Wijmo的配置以以便使用这些新设置。
$(document).ready(function () { var dataReader = new wijarrayreader([ { name: "Artist", mapping: "ArtistName" }, { name: "Album", mapping: "AlbumName" } ]); var dataSource = new wijdatasource({ proxy: new wijhttpproxy({ url: "@Url.Action("GetAlbumList")", dataType: "json" }), dynamic: true, reader: { read: function (datasource) { var count = datasource.data.TotalRowCount; datasource.data = datasource.data.Items; datasource.data.totalRows = count; dataReader.read(datasource); } } }); $("#remoteTable").wijgrid({ pageSize: 15, data: dataSource, allowPaging: true, allowSorting: true }); });
在最开始,我们打算声明一个新的datareader,用来读取来自服务器的JSON数据。它将告诉Wijmo如何将JSON属性映射到表格的列。
接下来是数据源。这是一个URL的代理。Wijmo会在这个URL上做一个GET操作以获取信息。这里dynamic关键字告诉Wijmo,服务器会接受排序,过滤以及分页请求。如果它被设置为false或者从来都没有设置过,Wijmo不会发送我们之前提到的请求参数。Reader告诉Wijmo如何解释数据,并且获取行数,之后是应用darareader。
最后一个调用是真正的创建WijGrid。这和你之前曾经看过的没有什么不同。唯一使得服务器收集数据的设置就是datasource。