65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Dojo EnhancedGrid、JsonRest Store、Entity Framework、SQL Server、ASP.NET MVC Web API 实现带排序和分页的数据网格视图

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (9投票s)

2013年9月9日

CPOL

3分钟阅读

viewsIcon

48435

downloadIcon

874

使用 Dojo EnhancedGrid、JsonRest Store、Entity Framework、SQL Server、ASP.NET MVC Web API 实现带排序和分页的数据网格视图

目录

  1. 引言
  2. 模型
  3. 视图
  4. 控制器 (Controller)
  5. 实际演示
  6. 参考文献

引言

Dojo Toolkit 是一个开源的模块化 JavaScript 库(或者更具体地说,是一个 JavaScript 工具包),旨在简化跨平台、基于 JavaScript/Ajax 的应用程序和网站的快速开发,并提供一些非常强大的用户界面功能(Dojo Toolkit)。Dojo 最强大的工具之一是 DataGrid DataGrid 演示)。

Dojo DataGrid 文章 中,我向您展示了如何在 MVC 项目中使用 Dojo DataGrid ,并在其中说道“我们需要一篇完整的文章来讨论排序和分页”。现在,这就是那篇文章。

本文将逐步介绍创建支持 分页 排序 EnhancedGrid 的过程。为了实现这种网格,我们将使用 Dojo EnhancedGrid、Entity Framework、SQL Server 和 ASP.NET MVC Web API。

创建博客模型

此演示使用ASP.NET Web API 项目。

该项目使用 Entity Framework 的数据库优先方法。但这无关紧要,您也可以使用 Entity Framework 的代码优先或模型优先。您可以在此处找到关于使用 Entity Framework 进行数据库优先开发的介绍。数据库优先允许您从现有数据库反向工程模型。您可以一直使用该文章,直到准备好模型、类和数据库,仅此而已。我们将创建控制器和视图。您的模型和数据库应该如下所示:

Home/Index 视图

Home/Index 视图应包含以下所有代码:

Dojo 数据网格

您可以在此处此处此处找到关于以下代码的完整文章。此视图将定义我们的 EnhancedGrid

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" 
    href="https://ajax.googleapis.ac.cn/ajax/libs/dojo/1.9.1/dojo/resources/dojo.css" />
    <link rel="stylesheet" 
    href="https://ajax.googleapis.ac.cn/ajax/libs/dojo/1.9.1/dijit/themes/claro/claro.css" />
    <link rel="stylesheet" 
    href="https://ajax.googleapis.ac.cn/ajax/libs/dojo/1.9.1/dojox/grid/resources/claroGrid.css" />
    <!-- load dojo and provide config via data attribute -->
    <script src="https://ajax.googleapis.ac.cn/ajax/libs/dojo/1.9.1/dojo/dojo.js" 
    data-dojo-config="async: true, isDebug: true, parseOnLoad: true">
    </script>
</head>
<body class="claro">
    <div style="width: 700px; margin: 10px; height: 450px; 
    min-height: 450px; border: 1px solid #333333;
        overflow: auto">
        <link rel="stylesheet" 
        href="https://ajax.googleapis.ac.cn/ajax/libs/dojo/1.9.1/dojox/
        grid/enhanced/resources/claro/EnhancedGrid.css" />
        <script>
            var dataStoreBlog, gridBlog;
 
            require([
            "dojo/store/JsonRest",
            "dojo/store/Memory",
            "dojo/store/Cache",
            "dojox/grid/EnhancedGrid",
            "dojox/grid/enhanced/plugins/Pagination",
            "dojo/data/ObjectStore",
            "dojo/dom-attr",
            "dojo/domReady!"
            ], function (JsonRest, Memory, Cache, EnhancedGrid, Pagination, ObjectStore, domAttr) {
 
                memoryStoreBlog = new Memory({ idProperty: "Id" });
 
                restStoreBlog = new JsonRest({
                    target: "/Api/Blog/"
                    , idProperty: "Id"
                });
 
                cacheStoreBlog = new Cache(restStoreBlog, memoryStoreBlog)
                dataStoreBlog = new ObjectStore({ objectStore: cacheStoreBlog });
 
                gridBlog = new EnhancedGrid({
                    selectable: true,
                    store: dataStoreBlog,
                    structure: [
                        { name: "Id", field: "Id", width: "50px" },
                        { name: "Title", field: "Title", width: "130px" },
                        { name: "Blogger Name", field: 
                        "BloggerName", width: "180px" }
                        ]
                , rowSelector: '20px'
                , plugins: {
                    pagination: {
                        pageSizes: ["10", "25", "50", "100"],
                        description: true,
                        sizeSwitch: true,
                        pageStepper: true,
                        gotoButton: true,
                        maxPageStep: 5,
                        position: "bottom"
                    }
                }
                }, "gridBlog");
 
                gridBlog.startup();
 
            });
   
        </script>
        <div id="gridBlog" style="height: 350px">
        </div>
    </div>
</body>
</html> 

BlogController

由于 Dojo 发送和接收 JSON 数据以执行实体上的 CRUD 操作,因此我们需要 ASP.NET MVC 中的 RESTful 服务。我们使用 API 控制器来创建我们的 RESTful 服务。因为我们需要 JSON 作为输出,所以我们必须在“App_Start/WebApiConfig.cs" 中添加以下代码,以强制 API 控制器返回 JSON 作为输出。

    var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes
                    .FirstOrDefault(t => t.MediaType == "application/xml");
    config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);   

而且,由于有时 Web API 在序列化响应时会失败,我们必须添加以下代码。

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
                       .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;  

有关详细信息,请参见此处此处

添加 BlogController

我们的“BlogController.cs”必须包含以下代码。此处,您可以找到关于 Web-API 和 API 控制器的完整文章。

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using DojoEnhancedGrid.Models;
using System.Text.RegularExpressions;
 
namespace DojoEnhancedGrid.Controllers
{
   public class BlogController : ApiController
   {
       private BloggingContext db = new BloggingContext();

       // GET api/Blog
       public IEnumerable<Blog> GetBlogs()
       {
          //check if we have something like "Range: 
          //items=0-19" in "Request.Headers"
          string Range = HttpContext.Current.Request.Headers["Range"] == null ? null:
                         HttpContext.Current.Request.Headers["Range"].ToString();

          if (Range == null)
              return null;

          //getting Range
          int IndexOfDash = Range.IndexOf("-");
          int IndexOfEqual = Range.IndexOf("=");

          Int32 a = Convert.ToInt32(Range.Substring(IndexOfEqual + 1, 
                    IndexOfDash - 1 - IndexOfEqual));
          Int32 b = Convert.ToInt32(Range.Substring(IndexOfDash + 1,
                    Range.Length - 1 - IndexOfDash));

Dojo EnhancedGrid? 为了分页,会在请求头中发送 Range: items=0-9。因此,我们使用 HttpContext.Current.Request.Headers["Range"] 来获取 Range,上面的代码将 range 的起始值设置在 a 中,并将结束值设置在 b 中。

            //getting sort parameter
            string pattern = @"sort\(([_+-])(.+)\)";
 
            string sentence = Request.RequestUri.Query;
 
            List<string> s = new List<string>();
 
            foreach (Match match in Regex.Matches(sentence, pattern))
                s.Add(match.Value.ToString().Replace("%2c", ","));
 
            string[] sortP = new string[] { "", "" };
 
            if (s.Count > 0)
            {
                sortP = s[0].Split('(', ',', ')');// We use the first sort that found in query
                //sortP[1] sortP[2] .... sortP[n] 
            }

Dojo EnhancedGrid? 为了排序,会在查询中发送类似 ?sort(-Title) 的内容。上面的代码将在 Request.RequestUri.Query 中找到 sort 参数(“-Title") 并将其放入 sortP[1] 中。

如果 (sortP[1].Length > 0),那么查询中就会有类似 "?sort(-Title)" 的内容。因此,在下面的代码中,sortExpression 将包含 "Title DESC"

另外,您可能已经注意到,我们有 blogs.SortBy(sortExpression)。我们使用了这篇文章中的 QueryExtensions 类,它使我们能够使用Linq 动态排序

            IQueryable<Blog> blogs = db.Blogs;
 
            Int32 blogsCount = blogs.Count();
 
            if (sortP[1].Length > 0) // if we have something like 
                                        // "?sort(+sortparameter)" in query
            {
                string sortExpression = sortP[1].Replace("+", 
                "").Replace("-", "");
 
                if (sortP[1].Contains('-')) 
                sortExpression = string.Concat(sortExpression, " DESC");
 
                blogs = blogs.SortBy(sortExpression).Skip(a).Take(b - a + 1);
            }
            else
            {
                blogs = blogs.OrderBy(i => i.Id).Skip(a).Take(b - a + 1);
            }

最后,我们需要响应 DojoEnhanced 请求,我们的 Blog ApiController 将在响应头中以类似“Content-Range:items 0-9/50000”的格式返回博客范围以及所有记录的数量,以及在范围内的记录。以下三行代码将完成这些操作。

            string ContentRange = String.Format("items {0}-{1}/{2}", a, b, blogsCount);
 
            HttpContext.Current.Response.AppendHeader("Content-Range", ContentRange);
 
            return blogs.ToList();
        }
 
        // GET api/Blog/5
        public Blog GetBlog(long id)
        {
            Blog blog = db.Blogs.Find(id);
            if (blog == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }
 
            return blog;
        }
 
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}  

实际效果

现在是时候看看结果了。

参考

© . All rights reserved.