Here is how I created a paged items list in ASP.NET 3.5 using Subsonic for data access, and ASP.NET Controls for the display.
I use Subsonic 3.0.0.4 with ActiveRecord and ASP.NET 3.5 SP1 webforms.
For this example, we are creating a blog post list and that the DAL is created (the data class we use is “DAL.BlogPost”).
The DAL.BlogPost object has three properties we need : CreatedOn, Subject and Body.
First step : prepare your data manager class
namespace MyBlog.BLL { public class PostManager { // ... } }
(keep in mind the namespace and the class for the nexts steps)
In this class, two methods are required,
The first returns the total number of items
public int GetPostCount() { return DAL.BlogPost.All().Count(x => x.IsDeleted != true); }
The second one returns the items contained in a defined range (start index and then nomber of elements), so this method needs to know where to start and how many items to get.
public PagedList<DAL.BlogPost> GetLastestPosts(int startRowIndex, int maximumRows) { if (startRowIndex != 0) { startRowIndex =(startRowIndex/maximumRows); } IOrderedQueryable<DAL.BlogPost> yourQuery = DAL.BlogPost.All().OrderByDescending(x => x.CreatedOn); return new PagedList<DAL.BlogPost>(yourQuery, startRowIndex, maximumRows); }
One important part to remember when using Subsonic is
if (startRowIndex != 0) { startRowIndex = startRowIndex / maximumRows; }
This conversion is necessary because subsonic and the ObjectDataSource doesn’t share the same opinion about the paging method.
Subsonic says
“I want the third page containing five elements”
ObjectDataSource says
“I want the five elements following the third element”
So the conversion is mandatory if you want a correct paging.
Second step : create the aspx page.
Declare an ObjectDataSource:
<asp:ObjectDataSource runat="server" ID="postsDataSource" TypeName="Example.BLL.PostManager" SelectMethod="GetLastestPosts" EnablePaging="true" SelectCountMethod="GetPostCount" > </asp:ObjectDataSource>
Note the TypeName attribute : the value is the namespace + the class name of our datamanager class.
We set the EnablePaging attribute to true and we specify the SelectCountMethod and the SelectMethod.
We don’t need any parameters for the paging, by default the MaximumRowsParameterName and StartRowIndexParameterName are set to “maximumRows” and “startRowIndex”.
If we want other parameters names in our datamanager class, we can define them in the ObjectDataSource with these two parameters.
Add an asp ListView element
<asp:ListView runat="server" ID="postsListview" DataSourceID="postsDataSource"> <LayoutTemplate> <asp:PlaceHolder ID="itemPlaceHolder" runat="server" /> </LayoutTemplate> <ItemTemplate> <h2><%# Eval("CreatedOn","{0:d}")%> : Â <%# Eval("Subject") %></h2> <br /> <p> <%# Eval("Body") %> </p> <hr /> </ItemTemplate> </asp:ListView>
Set the DataSourceID attribute to the ObjectDataSource ID parameter.
Define a LayoutTemplate and an ItemTemplate with the elements we want to display.
Then add an asp datapager control in the LayoutTemplate
<LayoutTemplate> <asp:DataPager ID="postsDataPager" runat="server" PageSize="3"> <Fields> <asp:NextPreviousPagerField ButtonType="Link" Â FirstPageText="<<" PreviousPageText="<" ShowNextPageButton="false" ShowFirstPageButton="true" /> <asp:NumericPagerField PreviousPageText="..." NextPageText="..." ButtonCount="10" /> <asp:NextPreviousPagerField ButtonType="Link" LastPageText=">>" NextPageText=">" ShowPreviousPageButton="false" ShowLastPageButton="true" /> </Fields> </asp:DataPager> <asp:PlaceHolder ID="itemPlaceHolder" runat="server" /> </LayoutTemplate>
Remark about the data access method
It’s possible to avoid the start index value conversion !
Check the PagedList first constructor code (code is available on the subsonic git repository)
public PagedList(IQueryable<T> source, int index, int pageSize) { int total = source.Count(); TotalCount = total; TotalPages = total / pageSize; if(total % pageSize > 0) TotalPages++; PageSize = pageSize; PageIndex = index; AddRange(source.Skip(index * pageSize).Take(pageSize).ToList()); }
As you can see, Subsonic use the Skip and the Take methods from Linq
So, you can modify the GetLastestPosts method to return a strongly typed List in place of the PagedList:
public List<DAL.BlogPost> GetLastestPosts(int startRowIndex, int maximumRows) { return DAL.BlogPost.All(). Skip(startRowIndex). Take(maximumRows). OrderByDescending(x => x.CreatedOn). ToList<DAL.BlogPost>(); }
With this method, no more conversion needed
Incoming search terms:
- define: net gaming-addiction
- how to use subsonic in visual studio 2015
This article was extremely helpful – by far the best I’ve seen on the subject and I’ve been googling it a plenty – but while this takes care of the paging it doesn’t address the need for sorting. Assuming you still use subsonic, what are your recommendations for handling sort through the ODS?
Thanks in advance,
[...] This post was mentioned on Twitter by Didier Danse, Samuel Beauvois. Samuel Beauvois said: New blog post : Custom paging with Subsonic 3 and ObjectDataSource in ASP.NET. http://bit.ly/djQvKH [...]