Click here to Skip to main content
Click here to Skip to main content

DataGrid View with Sorting and Paging using Dojo EnhancedGrid, JsonRest Store, Entity Framework, SQL Server, ASP.NET MVC Web API

, 8 Sep 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
DataGrid View with Sorting and Paging using Dojo EnhancedGrid, JsonRest Store, Entity Framework, SQL Server, ASP.NET MVC Web API

Table of Contents

  1. Introduction
  2. Model
  3. View
  4. Controller
  5. See in action
  6. References

Introduction

Dojo Toolkit is an open source modular JavaScript library (or more specifically JavaScript toolkit) designed to ease the rapid development of cross-platform, JavaScript/Ajax-based applications and web sites and provides some really powerful user interface features (Dojo Toolkit). One of the most powerful Dojo tools is DataGrid (DataGrid demo).

In Dojo DataGrid article, I showed you how to use Dojo DataGrid in an MVC project and there, I said that "we need a full article to talk about sorting and paging". Here you are.

This article walks-through the process of creating an EnhancedGrid supporting Paging and Sorting. For making this kind of grid, we will use Dojo EnhancedGrid, Entity Framework, SQL Server and ASP.NET MVC Web API.

Creating Blog Model

This demo uses an ASP.NET Web API Project.

This project uses Entity Framework Database First approach. But this isn't the point, you could also use Entity Framework Code First or Model First. Here, you could find an introduction to Database First development using Entity Framework. Database First allows you to reverse engineer a model from an existing database. You could use the article until you've got your model, your classes and your database in place, nothing more. We will make our controllers and views. Your Model and Database should be something like this:

Home/Index View

Home/Index View should contain all the codes below:

Dojo Data Grid

You could see a complete article about the code below in here and here or here. This view will define our EnhancedGrid.

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" 
    href="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/resources/dojo.css" />
    <link rel="stylesheet" 
    href="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dijit/themes/claro/claro.css" />
    <link rel="stylesheet" 
    href="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojox/grid/resources/claroGrid.css" />
    <!-- load dojo and provide config via data attribute -->
    <script src="http://ajax.googleapis.com/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="http://ajax.googleapis.com/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

As Dojo sends and receives JSON data to perform CRUD operations on the entities, so we need RESTful service within an ASP.NET MVC. We use API controller to make our RESTful service. Because we need Json as output, we must add the following codes to "App_Start/WebApiConfig.cs" to force API controller to return Json as output:

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

and because sometimes Json failed to serialize the response in Web API, we must add the following codes:

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

See here and here for detail.

Adding BlogController

Our "BlogController.cs" must contain the following codes. Here, you could find complete articles about Web-API and API Controller.

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? for paging sends Range: items=0-9 in header. So we use HttpContext.Current.Request.Headers["Range"] for getting the Range, and the code above, set the start of range in a and set the end of range in 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? for sorting send something like ?sort(-Title) in query. The code above will find sort parameter ("-Title") in Request.RequestUri.Query and put it in sortP[1].

if (sortP[1].Length > 0) so we have something like "?sort(-Title)" in query. So in code below sortExpression will contain "Title DESC".

Also as you have noticed, we have blogs.SortBy(sortExpression). We use QueryExtensions class in this article that enables us to use Dynamic Sorting with 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);
            }

Finally, we need to respond to DojoEnhanced request, the range that our Blog ApiController will return and the amount of all records in Response Header in something like "Content-Range:items 0-9/50000" and the records that were in the range. The following three lines will do these:

            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);
        }
    }
}  

See in Action

Now it's time to see the result.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nikfazan
Software Developer (Senior)
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
نیک فزان
 
“If you can't explain it simply, you don't understand it well enough.”
Albert Einstein

Comments and Discussions

 
GeneralSEO friendly / search engine friendly Pinmember_H2_15-Sep-13 10:01 
GeneralRe: SEO friendly / search engine friendly PinprofessionalNikfazan15-Sep-13 11:55 
GeneralMy vote of 3 Pinmemberstolbovoy10-Sep-13 7:02 
AnswerRe: My vote of 3 [modified] PinmemberNikfazan10-Sep-13 7:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150128.1 | Last Updated 9 Sep 2013
Article Copyright 2013 by Nikfazan
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid