One (MVC) Grid to Rule Them All

Posted by on in Blogs
Imagine you're starting a new project using ASP.NET MVC. Let's say it's a project which frequently requires displaying a list of records, like Google or Stack Overflow or an enterprise database application. Which grid should you use?

The obvious answer is, "I don't know. I'm just getting started. Does it really matter, right now?" Don't you wish!

There are many grids available for ASP.NET MVC. If you're prepared to dedicate your project to a single grid at the outset of your project, and never change it, nor support alternate platforms, like mobile, then you can (almost) be a happy developer. But if you think you might want to support mobile devices, tablets, and desktop browsers with the same application, if you acknowledge the possibility that you might want to change your mind about which grid you will use in the future, or if you care about separation of concerns, then you may have a problem.

Most grids don't support ASP.NET MVC very well. In particular, they often:

  • Push presentation concerns into the controller. In my opinion, the specific grid you choose in the manner in which it is rendered (column headers, search features, paging, etc.) is a presentation concern, and belongs in the view portion of an application with MVC architecture. Controllers should be grid-agnostic, both in the datatypes they use and in the way you structure your actions.

  • Render JavaScript inline. For best page rendering performance, JavaScript should be included at the very end of the body tag.

  • Don't support DataAnnotations and other features related to MVC 2's templates. If I have a view model which is marked up with DataAnnotations attributes like [DataType(DataType.Date)], then I should not have to do anything further in order to get a grid to display correctly.

  • Require too much code in too many places to get a decent grid on the page.

  • Don't support ASP.NET MVC at all. SlickGrid, for example, is a fairly popular JavaScript-based grid which suffers from being minimally documented and does not ship with an MVC interface. This is understandable, because writing a rich integration with ASP.NET MVC is a fair amount of work! What if there were an easier way...?


A while back, I published some simple examples of how to integrate jqGrid with ASP.NET MVC. I've used this general technique in real-world projects, but the lack of support for DataAnnotations/templated views in my code was becoming a maintenance issue; the technique I demonstrated there required writing too much JavaScript. I decided to go back and add support for MVC 2 templated views and generate the JavaScript. As I did so, however, I quickly realized that there was very little jqGrid-specific code in my project. I partitioned this off into its own namespace and added a feature allowing the user to specify a grid renderer at runtime. Mixing in fixes for all of the issues above, I now have the skeleton of a generic grid interface in place.

To be clear, I am not writing a new grid. Instead, I've written an interface which supports multiple grids, including jqGrid and even plain HTML tables, without requiring special, grid-specific code strewn throughout your application.

I'm releasing this as open source. Actually, it's already out, but it's not quite public yet. I have a few more pieces I need to put in place first, like a demo application.

In the meantime, I'd like to get some feedback on the API. My opinion is that most grids which have an MVC integration at all require the programmer to do far too much work in order to get a decently-formatted grid on the page. I admire the emphasis on API beauty which I see in the Rails community.

So I'll be "releasing" this a little early. It's not really ready for production use yet. Although the code is solid, I am still making fairly significant changes to the API. I want this to look right, and I'd appreciate the help of anyone reading this blog.

Or, continue on to the next post in this series, examining the API for views.


Comments

  • Guest
    Craig Wednesday, 22 December 2010

    Nice one, I will be sure to check it out. In general I think grids are over used though, often a UL/LI in html can do a similar thing when combined with a bit of CSS.

  • Guest
    Jon Kruger Wednesday, 22 December 2010

    Great idea! Check out mvccontrib, I used their fluent interface as a starting point for something like this for one of my projects. If anything it might give you some ideas.

  • Guest
    Marco Cantu Wednesday, 22 December 2010

    I'd be very interested specifically if this is not bound to ASP.NET but can use generic AJAX calls into a REST server (specifically a Delphi REST server, a topic I'm working a lot with).

  • Guest
    Dan Miser Thursday, 23 December 2010

    Great analysis. If you need more eyeballs, you know where to find me.

  • Guest
    manjunath ch Sunday, 9 January 2011

    Hi Craig
    i have the following jqgrid code which works fine with loading editing and deleting .
    I am using the form with button click event to load the jqgrid, which loads perfectly for the first click event.but the problem is if i change the search text and click the button its loading the same data that is loaded for first search.


    $(document).ready(function () {
    var firstClick = true;
    //var act = null;
    $('#search').click(function () {
    var datae = document.getElementById("email").value;
    datae;
    validate(datae);
    });
    function validate(datae) {
    if (/^([\w-]+(?:\.[\w-]+)*)@@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i.test(datae)) {
    getData(datae);
    }
    else {
    $.jnotify("Invalid E-mail Address! Please re-enter.", 2000);
    return false;
    }
    }
    function getData(data1) {
    alert(data1);
    if (!firstClick) {
    $("#list").trigger("reloadGrid");
    return true;
    }
    firstClick = false;
    jQuery("#list").jqGrid({
    url: 'AddSearch?mail=',data1
    // data:"[email protected]",
    datatype: 'json',
    mtype: 'get',
    colNames: ['GizaId', 'UserEmail', 'CustomURL', 'FullName', 'status', 'GizaPublicURL'],
    colModel: [
    { name: 'GizaProfileId', index: 'GizaProfileId', readonly: true, editable: false, width: 75, align: 'left' },
    { name: 'UserEmail', index: 'UserEmail', width: 100, align: 'left' },
    { name: 'CustomURL', index: 'CustomURL', width: 75, align: 'left' },
    { name: 'FullName', index: 'FullName', width: 100, align: 'left' },
    { name: 'status', index: 'status', width: 100, align: 'left' },
    { name: 'GizaPublicURL', index: 'gizaPublicURL', width: 150, align: 'left', formatter: 'link' },
    ],
    pager: jQuery('#pager'),
    height: 'auto',
    //rowList: null,
    rowList: 2,
    pgbuttons: false,
    viewrecords: true,
    pgtext: null,
    viewrecords: false,
    caption: 'GizaUserProfiles',
    imgpath: '../Scripts/themes/coffee/Images',
    scrollOffset: 0,
    loadComplete: function () { $('#subCont').show(); },
    loadError: function (xhr, st, err) {
    $.jnotify("No Data available for this id");
    }
    });
    jQuery("#list").navGrid("#pager", { refresh: false, edit: false, add: false, del: false, search: false });

    }

  • Guest
    Saurabh Thursday, 23 June 2011

    From where do I download the code.. I don't see any download link..

  • Guest
    Iconoclast Thursday, 19 September 2013

    I tsk, tsk at referencing (at the time of this writing) an already 3 year-old post about putting javascript at the end of the body.

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: