Developing ASP.NET MVC 3 Application with EF CTP (Part 5)

In this post I will describe how to use MVC with a jquery grid control to display tabular data.  To start with, there is a number of grids available, some even integrate with ASP.NET MVC by providing an MVC assembly that generates the javascript for the grid.  One of these components in jqGrid.  I am not going to use MVC helper for this demo primarily because MVC component is not a free download.  As a result, I am going to just download jqGrid itself from this site.  One of the files in download is a text file that describes what script and CSS files you need to include in your project.  I am going to just include a screenshots of my project.  I am only using one theme – swanky-purse.

image

 

image

Now, we need to incorporate those scripts into my master page (_Layout.cshtml) so that I do not have to download them in each view:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<
html xmlns
="http://www.w3.org/1999/xhtml">
<
head>
    <title>@View.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.1.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <link href="@Url.Content("~/Content/swanky-purse/jquery-ui-1.8.6.custom.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/ui.jqgrid.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery.ui.core.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.ui.datepicker.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/grid.locale-en.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.jqGrid.min.js")" type="text/javascript"></script
>
</
head
>
<
body>
    <div class="page">
        <div id="header">
            <div id="title">
                <h1>
                    My MVC Application</h1>
            </div>
            <div id="logindisplay">
                @Html.Partial("_LogOnPartial"
)
           
</div>
            <div id="menucontainer">
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Blogs", "Index", "Blogs")</li>
                </ul>
            </div>
        </div>
        <div id="main">
            @RenderBody()
           
<div id="footer">
            </div>
        </div>
    </div
>
</
body
>
</
html>
 

 

Now, we are going to plug in query grid script into the index page that shows blog entries – BlogsIndex.cshtml.  Here is the entire cshtml file:

@{
    View.Title = "Blogs";
    Layout =
"~/Views/Shared/_Layout.cshtml"
;
}

<h2>
    Index</h2
>
<
p>
    @Html.ActionLink("Create New", "Create")
</p
>
<
table id="blogsList" class="scroll" cellpadding="0" cellspacing
="0">
</
table
>
<
div id="blogsPager" class="scroll" style="text-align
: center;">
</
div>
 
<script type="text/javascript">
    $().ready(function
() {
        $(
"#blogsList"
).jqGrid({
            url:
‘./Blogs/BlogsGridData/’
,
            datatype:
‘json’
,
            mtype:
‘GET’
,
            colNames: [
, , ‘Title’, ‘Posted On’
],
            colModel: [
            { name:
‘Edit’, index: ‘Edit’, width: 80, align: ‘left’, sortable: false
},
            { name:
‘Delete’, index: ‘Delete’, width: 80, align: ‘left’, sortable: false
},
            { name:
‘Title’, index: ‘Title’, width: 300, align: ‘left’
},
            { name:
‘PostedOn’, index: ‘PostedOn’, width: 100, align: ‘left’
}],
            pager: $(
‘#blogsPager’
),
            rowNum: 2,
            rowList: [2, 5, 10, 20, 50],
            sortname:
‘PostedOn’
,
            sortorder:
"desc"
,
            viewrecords:
true
,
            caption:
‘Blogs’
        });
    });

</script
>

 

Let me describe the most interesting settings here.  Url is the most notable one.  It will be used to return json data for the grid.  I know I need json because my datatype is set as such.  The actual Url will be intercepted by the routing in ASP.NET MVC to my Blogs controller’s BlogGridData method.  I will show it momentarily.  I will have 4 columns (colNames) – two without headers.  Those two columns with contain edit and delete links (anchors).  The colModel property describes the layout of the columns.  Pager property simply points to a div that will be formatted as pager control for my grid.  I also specify default sort column name and direction.  The entire grid will be attached to my table with the name of blogist (see HTML portion of the cshtml file above).

Next, let me show you what my BlogGridData looks like.  I will start with the code for entire method:

        /// <summary>
        /// Get Json data for the grid
        /// </summary>
        /// <param name="sidx">Column to osrt on.  Do not change parameter name</param>
        /// <param name="sord">Sort direction.  Do not change parameter name</param>
        /// <param name="page">Current page.  Do not change parameter name</param>
        /// <param name="rows">Number of rows to get.  Do not change parameter name</param>
        /// <returns></returns>
        public ActionResult BlogsGridData(string sidx, string sord, int? page, int
? rows)
        {
           
using (BlogContext context = new BlogContext
())
            {
               
int
pageSize = rows ?? 2;
               
int
totalRecords = context.Entries.Count();
               
int totalPages = (int)Math.Ceiling((float)totalRecords / (float
)pageSize);
               
int
currentPage = page ?? 1;
               
string sortByColumnName = sidx ?? "PostedOn"
;
               
string sortDirection = sord ?? "desc"
;
 
               
var blogs = (from one in
context.Entries
                            
select
one);
               
if (sortByColumnName == "PostedOn"
)
                {
                   
if (sortDirection.Equals("desc"
))
                        blogs = blogs.OrderByDescending(blog => blog.PostedOn);
                   
else
                        blogs = blogs.OrderBy(blog => blog.PostedOn);
                }
               
else
                {
                   
if ("desc"
.Equals(sortDirection))
                        blogs = blogs.OrderByDescending(blog => blog.Title);
                   
else
                        blogs = blogs.OrderBy(blog => blog.Title);
                }
               
var
data = blogs.Skip((currentPage – 1) * pageSize).Take(pageSize).ToArray();
 
               
var jsonData = new jqGridJson
()
                {
                    total = totalPages,
                    page = currentPage,
                    records = totalRecords,
                    rows = (
                     
from blog in
data
                     
select new jqGridRowJson
                      {
                          id = blog.BlogEntryId.ToString(),
                          cell =
new string
[] { 
                               
"<a href=’" + string.Format("./Blogs/Edit/{0}", blog.BlogEntryId.ToString()) + "’>Edit</a>"
,
                               
"<a href=’" + string.Format("./Blogs/Delete/{0}", blog.BlogEntryId.ToString()) + "’>Delete</a>"
,
                                blog.Title, 
                                blog.PostedOn.Value.ToShortDateString() }
                      }).ToArray()
                };
 
               
return Json(jsonData, JsonRequestBehavior.AllowGet);
            }
        }

 

As you can see, I am creating Url’s for edit and delete links.  One important thing to remember is that parameters to any method (BlogsGridData) will be automatically parsed from query string, so you cannot change their names.  The names are hard coded in jqGrid.  In the beginning of the method I am parsing out page size, current page, etc…  Them I am selecting the data from my blogs table.  More specifically, I am creating IQueryable<BlogEntry>, which is my blogs variable.  This query actually is not executed until I access results, which is the line in bold. So, there on that line I am constructing classes that will be later serialized using json serializer.  The classes are simply helper classes because jqGrid again expects the result set in certain format.  Here are those two helper classes:

    public class jqGridJson
    {
       
public int total { get; set
; }
       
public int page { get; set
; }
       
public int records { get; set
; }
       
public jqGridRowJson[] rows { get; set; }
    }

    public class jqGridRowJson
    {
       
public string id { get; set
; }
       
public string[] cell { get; set; }
    }

 

At the end, my last line returns JsonResult class.  That is all there is to using jqGrid with MVC 3.0.  One important note is that Url’s that point to Controller methods are relative.  It took me a while to figure out why they are not invoked in IIS, but with in web server in Visual Studio.  Here is the screenshot of the final version running in IIS:

image

Please let me know if you have any questions.  You can download full solution here.

 

Thanks.

2 Comments

  1. Hi, thanks for this great tutorial.

    I have this error in my application:

    “Object [object Object] has no method ‘jqGrid'”

    I have included all javascript. If I try my code in an html page it works, but in a cshtml page not! I’m using MVC 4 WebApp.

    Thanks in advanced!

Leave a Reply

Your email address will not be published. Required fields are marked *