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.
- Require two requests in order to display the first page of data. One for the page itself, then a second, AJAX request for the data. I can understand why the AJAX request is necessary for the second page of grid data, but shouldn't the first page just come already populated? Making too many requests is one of the most common causes of performance problems in web applications. Worse, this decision bleeds into your Controller.
- Wait too long to set up the component in the browser. Unfortunately, they unnecessarily wait until the jQuery.ready event fires, resulting in unnecessary visual disruption and poor performances the page loads. It's often unnecessary to wait for the ready event, so you can visibly improve the perceived performance of the page by simply calling that method sooner!
- The two problems above compound each other. If you wait until the ready event fires to even issue a request for data, and then wait some more for that data to return, that can be a lot of waiting!
- 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,
AnyGrid is not a new grid. It is an interface which supports multiple grids, including jqGrid and even plain HTML tables, without requiring special, grid-specific code strewn throughout your application.