Recently I discovered that there’s no one standard way for AJAX-driven server-side paging in ASP.NET MVC (in Web API, you can expose an
IQueryable). For the case in hand, I decided to use PagedList for the server bit of the game.
PagedList interface looks a bit like this (for demonstration only, real code is a bit different, check its source code for the real stuff):
It provides nice properties for paging, and exposes itself as enumerable and has an indexer. Apart from this snippet, the library also provides an extension method
ToPagedList() to apply to any enumerable and allow it to populate the properties from it (by enumerating on it, and by calling the
The JSON.NET Serialization Problem
JSON.NET has a nice implementation, if you serialize a class that implements
Well, yes, except when you have a custom collection like
PagedList, and you want to treat it as an object that has several properties, not as an array. JSON.NET does provide a solution for this actually, all you need to do is apply the
[JsonObject] attribute to your class.
Unless you don’t own the source code of this class.
In this case, you need to inherit from it. By doing this, I lose the nice
ToPagedList() extention method (because it creates an object of the
PagedList class directly), but luckily it does nothing but calling
new PagedList() with the parameters we give it, so, we don’t lose much.
Here’s how my implementation looks like:
Apart from having to copy the constructors to pass parameters to the base ones, have you noticed the extra
Items property in there?
That’s because the
Subset member it includes is actually a field, not a property, and JSON.NET won’t serialize that by default, I could override it somewhere else, but since I’m fiddling with this here, it made sense to just stick a property to the class.
Bonus: A Bit More On Implementation
In my actual code, I have added the Dynamic Linq NuGet package, and assumed a single property for sorting (which was fair for the situations where I intend to use this), so, I complemented the code above with another class that looks like this:
This allows the controller to instantiate an instance of the
SerializablePagedList class, pass it all the way to whatever repository method I have.
The repository method will take it as a parameter, work out what
IQueryable it needs, and instead of passing it to UI, it calls
CreatePagedListFromQueryable(), which returns an innocent-looking
PagedList object (because
Even more, now that I think about it, maybe I should change the return type to
SerializablePagedList, to make the
Items property visible to the developer (because they’d think it’s magic, and in coding, magic is BAD). I’ll leave this as an exercise for you :)
Final Words / Disclaimer
The motivation behind this post is that I found the problem of serializing
PagedList using JSON.NET a challenge and I wanted to help others work it out faster than I did. Is this how I’d recommend doing paging? Well, I don’t know, but if it’s what you choose, I hope that I have saved you some time.
And more importantly, is it good enough to be the defacto standard I mentioned I was after in the beginning of the post? Not really. I think it’s not bad, but definitely not the best. I’d love to see less clever (read: hacky), and more simpler solutions.