When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, December 15, 2010

Displaying a Grid of Data in ASP.NET MVC

By Scott Mitchell


A Multipart Series on Grids in ASP.NET MVC
Displaying a grid of data is one of the most common tasks faced by web developers. This article series shows how to display grids of data in an ASP.NET MVC application and walks through a myriad of common grid scenarios, including paging, sorting, filtering, and client-side enhancements.

  • Displaying a Grid - this inaugural article walks through building the ASP.NET MVC demo application and retrieving and displaying database data in a simple grid.
  • Sorting a Grid - learn how to display a sortable grid of data.
  • Paging a Grid - shows how to efficiently page through a grid of data N records at a time.
  • Filtering a Grid - see how to create a filtering interface to limit what records are displayed.
  • Sorting and Paging a Grid - learn how to display a grid that is both sortable and can be paged.
  • Sorting, Paging, and Filtering - shows how to display a grid that is sortable, pageable, and filterable.
  • MvcContrib Grid - see how to use the free, open source MvcContrib Grid to display a grid of data.
  • Introduction


    One of the most common tasks we face as a web developers is displaying data in a grid. In its simplest incarnation, a grid merely displays information about a set of records - the orders placed by a particular customer, perhaps; however, most grids offer features like sorting, paging, and filtering to present the data in a more useful and readable manner.

    In ASP.NET WebForms the GridView control offers a quick and easy way to display a set of records in a grid, and offers features like sorting, paging, editing, and deleting with just a little extra work. On page load, the GridView automatically renders as an HTML <table> element, freeing you from having to write any markup and letting you focus instead on retrieving and binding the data to display to the GridView. In an ASP.NET MVC application, however, developers are on the hook for generating the markup rendered by each view. This task can be a bit daunting for developers new to ASP.NET MVC, especially those who have a background in WebForms.

    This is the first in a series of articles that explore how to display grids in an ASP.NET MVC application. This installment starts with a walk through of creating the ASP.NET MVC application and data access code used throughout this series. Next, it shows how to display a set of records in a simple grid. Future installments examine how to create richer grids that include sorting, paging, filtering, and client-side enhancements. We'll also look at pre-built grid solutions, like the Grid component in the MvcContrib project and JavaScript-based grids like jqGrid. But first things first - let's create an ASP.NET MVC application and see how to display database records in a web page.

    Read on to learn more!

    - continued -

    Step 0: A Brief Roadmap


    This article walks through creating an ASP.NET MVC 2.0 application in Visual Studio 2010 using C# and the default ASPX-style view engine. This project is used as the demo application in this article and in the remaining articles in this series, and can be downloaded from the end of any article in the series. After creating the ASP.NET MVC demo application, adding the Northwind database, and adding a data access layer using Linq-to-SQL, we will look at how to display data in a simple grid. Future installments will build atop the concepts presented in this article to add features like sorting, paging, filtering, and so on.

    Step 1: Creating a New ASP.NET MVC Project


    ASP.NET MVC is a Microsoft-supported framework for creating ASP.NET applications using a Model-View-Controller pattern. In a nutshell, ASP.NET MVC allows developers much finer control over the markup rendered by their web pages, a greater and clearer separation of concerns, better testability, and cleaner, more SEO-friendly URLs. The ASP.NET MVC framework was first introduced in the days of Visual Studio 2008 and ASP.NET 3.5 SP1, and can still be used in those earlier versions, although you'll need to download and install it. The ASP.NET MVC framework was shipped as part of the .NET framework starting with .NET 4, so if you are using Visual Studio 2010 and ASP.NET 4 there is nothing extra you need to install or configure in order to start developing ASP.NET MVC applications.

    New to ASP.NET MVC?
    Please note that this article series focuses on displaying grids in ASP.NET MVC application and is not intended to be an introduction or beginners tutorial to ASP.NET MVC (although I do include some beginner-level discussions in this article). For an introduction to ASP.NET MVC, check out these Getting Started with MVC tutorials or Scott Guthrie's free NerdDinner chapter (PDF) from Professional ASP.NET MVC 2.0.

    Let's get started creating a new ASP.NET MVC application. Begin by launching Visual Studio and going to File -> New Project. Select the ASP.NET MVC 2 Empty Web Application template; name the Solution GridDemosMVC and the Name of the project Web and click OK (see the screen shot below).

    Create a new ASP.NET MVC application using the ASP.NET MVC 2 Empty Web Application template.

    A new ASP.NET MVC project - even a so-called "empty" one - consists of a number of default files and folders: The default files and folders added to the ASP.NET MVC project.

    • Content - this folder is designed to contain static site content, such as CSS files, images, and so on.
    • Controllers - this folder will contain the application's Controllers. In MVC, the Controller is responsible for handling the incoming request and choosing a Model and View to generate the response. Controllers are implemented as classes and their methods - which are referred to as actions - are automatically invoked when a URL of the appropriate format is requested.
    • Models - this folder is used to hold the Models. Models are implemented as classes and contain the data and business logic for a particular request.
    • Scripts - this folder contains the jQuery and Microsoft ASP.NET Ajax Library JavaScript files.
    • Views - this folder holds the Views, which are responsible for generating the content returned to the requestor. Views typically contain a mix of HTML, JavaScript, and server-side code. Unlike the WebForms model, where the server-side code is located in a separate code-behind class, with views the server-side code and markup are placed in the same page and are intermingled. Moreover, the server-side code in Views is typically very simple, serving only to loop through the data in the Model so as to generate the page's markup. A View's server-side code should not contain business logic.
    • Global.asax - behind the scenes, ASP.NET MVC uses ASP.NET Routing extensively. By default, ASP.NET MVC applications contain a single routing rule that defines the following URL pattern: {controller}/{action}/{id}. When a URL arrives to the site, such as www.yoursite.com/Categories/View/Beverages, ASP.NET MVC executes the controllerController class's action method, passing in the id as an input parameter to the method. In the case of www.yoursite.com/Categories/View/Beverages, ASP.NET MVC would execute the CategoryController class's View method, passing in the string Beverages as the input parameter to the method.
    At this point we have the skeleton of our ASP.NET MVC application!

    Step 2: Adding the Northwind Database and Creating the Linq-To-SQL Classes


    Before we start adding Controllers and Views, let's first get our Models and database squared away. The demos in this article series display data from the Northwind database, which you can find in the download at the end of this article. Create an App_Data folder in your project and add the two database files, northwnd.mdf and northwnd.ldf.

    Now we need some way to access the data from the database. There are a variety of data access options available; for this article series I decided to go with Linq-to-SQL, which is an object-relational mapping (O/RM) tool from Microsoft. I chose Linq-to-SQL because it is, perhaps, the quickest and easiest O/RM to get started with. (I didn't want to get bogged down on the data access side since this article series is aimed more at displaying data in a grid than it is at retrieving data from a database.) In a nutshell, using Linq-to-SQL entails adding a special file to our project that specifies what database table(s) we need to access. Linq-to-SQL then creates classes that model these tables as well as a DataContext class that is used to update and retrieve data to and from the database. Linq-to-SQL allows us to programmatically work with our database's data using terse, readable code that is strongly-typed, meaning we get to enjoy compile-time type checking, IntelliSense, and so on. With Linq-to-SQL (or any O/RM, for that matter) there's no need waste your time writing low-level ADO.NET code or craft SQL statements. If you are not familiar with Linq-to-SQL, or are just getting started, I highly recommend Scott Guthrie's excellent tutorials on getting started with Linq-to-SQL.

    Because we will be using the classes created by Linq-to-SQL as the Models in our application, add the Linq-to-SQL file to the Models folder. Specifically, right-click on the Models folder and choose to add a new file. From the dialog box, select the LINQ to SQL Classes template and name the file Northwind.dbml. This will create the new file and open it, showing you the Linq-to-SQL designer.

    Add the Linq-to-SQL file to your project.

    Next, go to the Server Explorer and expand the northwnd.mdf database. Drag both the Categories and Products tables onto the design surface and then save your changes.

    That's all there is to it! At this point we have our data access layer in place.

    Step 3: Adding the Content Files to the Project


    If you're following along from your computer, you should have the folders and files from when you first created the ASP.NET MVC application, as well as the App_Data and the Northwind database files, and the Northwind.dbml file in the Models folder. There are a number of additional content files used in the demo available for download at the end of this article, which include images and CSS files in the Content folder. Please take a moment to download the demo application and copy the files from the demo's Content into your application's Content folder.

    Also copy the demo's Site.Master file from the Views/Shared folder into your project's Views/Shared folder. The Site.Master file is a master page for the application and defines the site-wide look and feel.

    Do not copy over any other files and folders from the demo application - we'll be creating those ourselves in this article or in subsequent installments.

    Step 4: Adding the ProductsController Controller


    For this demo, all grid samples will fall under a single controller named ProductsController. For instance, the simple grid examined in this article will be served from the Index action, meaning it will be accessible via www.yoursite.com/Products/Index (or just www.yoursite.com/Products, since Index is the default action name), whereas the sorting and paging demos will be accessible via www.yoursite.com/Products/Sortable and www.yoursite.com/Products/Paged.

    To create a new Controller, right-click on the Controllers folder and choose Add -> Controller; name this new Controller ProductsController and click Add. Doing so will create a new class named ProductsController with an Index method.

    public class ProductsController : Controller
    {
       // GET: /Products/
       public ActionResult Index()
       {
          return View();
       }

    }

    When a visitor reaches www.yoursite.com/Products/Index, we will display the name, category name, quantity per unit, price, and discontinued status for all products in the Products table. To get this information we need to use the NorthwindDataContext class, which is one of the classes auto-generated by the Linq-to-SQL tool. Because we'll need to work with the NorthwindDataContext class in all of the actions in this Controller, I decided to add a property to the class named DataContext that returns an instance of this class. Additionally, this property configures the created NorthwindDataContext instance so that it eager loads category information, since we'll often be displaying category details for each product. (By default, Linq-to-SQL lazy loads related entities, meaning that if we get back a set of products , Linq-to-SQL will go back to the database each time we access category information for a product (such as the product's category's name). If we know that we'll need the category information for each product, it's more efficient to eagerly load it, meaning the category information is retrieved at the same time as getting the product information. This saves us from having to go back to the database when accessing category information for a specific product.)

    Add the following DataContext property related code to the ProductsController class:

    public class ProductsController : Controller
    {
       private NorthwindDataContext _DataContext = null;
       protected NorthwindDataContext DataContext
       {
          get
          {
             if (_DataContext == null)
                _DataContext = new NorthwindDataContext();

             // Eager load Category info
             var options = new DataLoadOptions();
             options.LoadWith<Product>(p => p.Category);
             _DataContext.LoadOptions = options;

             return _DataContext;
          }
       }


       // GET: /Products/
       public ActionResult Index()
       {
          return View();
       }
    }

    The purpose of a Controller action is two-fold: to create the Model and determine what View to use to render the output. The return View() statement handles the latter part - selecting the View - but we've yet to specify the Model. Because we want the View to display certain fields of all products, we can have the Model simply be the set of Product objects in the database. This information can be retrieved using the following code:

    var model = this.DataContext.Products;

    But how do we get this Model to the View? There are two ways the Controller can pass the Model to the View:

    • Through the loosely-typed ViewData collection, or
    • By using a strongly-typed View.
    The latter approach is preferred and is the technique we'll use. To send a strongly-typed Model to the view you simply pass is as the first argument to the View method in the return statement. The code snippet below shows the updated code for the Index method.

    public class ProductsController : Controller
    {
       ...

       // GET: /Products/
       public ActionResult Index()
       {
          var model = this.DataContext.Products;

          return View(model);
       }
    }

    Step 5: Creating the View


    To create a View for the Index action, right-click on the method name and choose the Add View menu option. This will bring up the dialog box shown below. Leave the View Name as Index, but check the "Create a strongly-typed view" checkbox and choose the Web.Models.Product class from the drop-down. Check the "Select master page" checkbox if it is not already checked and use the ~/Views/Shared/Site.Master file as the master page. (Recall that you copied this file from the demo application to your application back in Step 3.)

    Add a strongly-typed View for the Index action.

    Adding this new View will create a Products subfolder and Index.aspx file within your Views folder. Take a moment to inspect the View's @Page directive at the top. The Inherits attribute should specify the View's strongly-typed Model as Web.Models.Product. Because the DataContext.Products property returns a collection of Product objects we need to change this to an enumeration of Web.Models.Product objects. To accomplish this, modify the @Page directive so that it looks like the following:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Web.Models.Product>>" %>

    At this point we're ready to construct the markup to be returned by the View. Because we are displaying a grid of data, let's use the HTML <table> element to display the data. Start by adding a <table> element and a header row. As noted earlier, our grid is to display the name, category name, quantity per unit, price, and discontinued status of each product. Consequently, our header row defined five columns.

    <table class="grid">
       <tr>
          <th>Product</th>
          <th>Category</th>
          <th>Qty/Unit</th>
          <th>Price</th>
          <th>Discontinued</th>
       </tr>
       
       ...

    The <table> has its class attribute set to grid - this is a CSS class definition in the sinorcaish-screen.css file that defines certain formatting properties.

    To display the data rows we need to loop through the set of Products in the Model. From within the View we can access the Model created by the Controller by using the Model property. The following foreach loop enumerates each Product object in the Model and emits a table row. Note how the String.Format method is used to format the UnitPrice as a currency. For the Discontinued column nothing is emitted if the product is not discontinued, but for those that are an image - cancel.png - is displayed.

    After the products have been displayed the markup is completed with the closing <table> tag.

    ...

    <% foreach (var item in Model) { %>
       
       <tr>
          <td class="left"><%: item.ProductName %></td>
          <td class="left"><%: item.Category.CategoryName %></td>
          <td class="left"><%: item.QuantityPerUnit %></td>
          <td class="right"><%: String.Format("{0:C}", item.UnitPrice) %></td>
          <td>
             <% if (item.Discontinued) { %>
                <img src="<%=Url.Content("~/Content/cancel.png") %>" alt="Discontinued" title="Discontinued" />
             <% } %>
          </td>
       </tr>
       
    <% } %>

    </table>

    And that's all there is to it!

    If you visit the page through a browser - www.yoursite.com/Products or www.yoursite.com/Products/Index - you will see a nicely formatted grid listing all of the products in the Northwind database.

    The products are listed in a simple grid.

    Conclusion and Looking Forward...


    This article showed how to create an ASP.NET MVC application and display data in a simple grid. With this foundation laid, we're ready to look at more interesting and intricate grid examples. Future articles in this series will explore how to add sorting, paging, and filtering capabilities, as well as a look at using off the shelf options, such as MvcContrib and jqGrid.

    Until then... Happy Programming!

  • By Scott Mitchell


    Attachments:

  • Download the Demo Code Used in this Article

    Further Reading

  • Getting Started with MVC Tutorials
  • Scott Guthrie's Free NerdDinner Chapter from Professional ASP.NET MVC 2.0 (PDF)
  • Scott Guthrie's Linq-to-SQL Tutorials


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article