<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SquaredRoot &#187; C#</title>
	<atom:link href="http://www.squaredroot.com/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.squaredroot.com</link>
	<description>.Net Development in DC</description>
	<lastBuildDate>Sun, 16 Aug 2009 01:30:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>PagedList Strikes Back</title>
		<link>http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/</link>
		<comments>http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 05:54:15 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[paging]]></category>

		<guid isPermaLink="false">/post/2008/07/08/PagedList-Strikes-Back.aspx</guid>
		<description><![CDATA[There is an updated version of the PagedList&#60;T&#62; code available here. A few months ago I posted about my changes to Rob Conery&#8217;s PagedList class. Since writing that article many comments have been left about how to further improve the design, which I have since incorporated into a new, further improved PagedList class. For those [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>There is an updated version of the PagedList&lt;T&gt; code available <a href="http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/">here</a>.</p></blockquote>
<p>A few months ago I posted about <a href="http://www.squaredroot.com/post/2008/04/08/Updated-PagedList-Class.aspx">my changes</a> to <a href="http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/">Rob Conery&#8217;s PagedList</a> class. Since writing that article many comments have been left about how to further improve the design, which I have since incorporated into a new, further improved PagedList class. For those who aren&#8217;t familiar, the PagedList class allows scenarios such as the following:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> ListProducts( <span class="kwrd">int</span> pageIndex )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">int</span> pageSize = 10;</pre>
<pre class="alteven"><span class="lnum">   4:</span>     var products = productRepository.GetAllProducts()</pre>
<pre class="alt"><span class="lnum">   5:</span>         .ToPagedList( pageIndex, pageSize );</pre>
<pre class="alteven"><span class="lnum">   6:</span>     <span class="kwrd">return</span> View( products );</pre>
<pre class="alt"><span class="lnum">   7:</span> }</pre>
</div>
</div>
<p><span id="more-14"></span><br />
So in the above scenario (an example MVC action), if you had a list of 30 products with IDs 1-30 and passed in a pageIndex of 2 you would pass the products with IDs 21-30 into your view. Best of all it uses IQueryable, so if you pass a LINQ expression or IQueryable result into ToPagedList(&#8230;) it will do the filtering on the database side! Take a look at the new improved PagedList:</p>
<p><strong>Update</strong>: <em>Per a suggestion in a </em><a href="http://blogs.taiga.nl/martijn/archive/2008/08/27/paging-with-asp.net-mvc.aspx"><em>post by Martijn Boland</em></a><em>, I have tweaked the code below by converting IPagedList to IPagedList&lt;T&gt; and having it implement IList&lt;T&gt;. This will allow you to pass the IPagedList&lt;T&gt; around and still enumerate it in a strongly-typed manner. Also of note is Martijn&#8217;s use of the PagedList class to </em><a href="http://blogs.taiga.nl/martijn/archive/2008/08/27/paging-with-asp.net-mvc.aspx"><em>create an MVC pager control</em></a><em>.</em></p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">using</span> System.Linq;</pre>
<pre class="alteven"><span class="lnum">   2:</span></pre>
<pre class="alt"><span class="lnum">   3:</span> <span class="kwrd">namespace</span> System.Collections.Generic</pre>
<pre class="alteven"><span class="lnum">   4:</span> {</pre>
<pre class="alt"><span class="lnum">   5:</span>     <span class="kwrd">public</span> <span class="kwrd">interface</span> IPagedList&lt;T&gt; : IList&lt;T&gt;</pre>
<pre class="alteven"><span class="lnum">   6:</span>     {</pre>
<pre class="alt"><span class="lnum">   7:</span>         <span class="kwrd">int</span> PageCount { get; }</pre>
<pre class="alteven"><span class="lnum">   8:</span>         <span class="kwrd">int</span> TotalItemCount { get; }</pre>
<pre class="alt"><span class="lnum">   9:</span>         <span class="kwrd">int</span> PageIndex { get; }</pre>
<pre class="alteven"><span class="lnum">  10:</span>         <span class="kwrd">int</span> PageNumber { get; }</pre>
<pre class="alt"><span class="lnum">  11:</span>         <span class="kwrd">int</span> PageSize { get; }</pre>
<pre class="alteven"><span class="lnum">  12:</span>         <span class="kwrd">bool</span> HasPreviousPage { get; }</pre>
<pre class="alt"><span class="lnum">  13:</span>         <span class="kwrd">bool</span> HasNextPage { get; }</pre>
<pre class="alteven"><span class="lnum">  14:</span>         <span class="kwrd">bool</span> IsFirstPage { get; }</pre>
<pre class="alt"><span class="lnum">  15:</span>         <span class="kwrd">bool</span> IsLastPage { get; }</pre>
<pre class="alteven"><span class="lnum">  16:</span>     }</pre>
<pre class="alt"><span class="lnum">  17:</span></pre>
<pre class="alteven"><span class="lnum">  18:</span>     <span class="kwrd">public</span> <span class="kwrd">class</span> PagedList&lt;T&gt; : List&lt;T&gt;, IPagedList</pre>
<pre class="alt"><span class="lnum">  19:</span>     {</pre>
<pre class="alteven"><span class="lnum">  20:</span>         <span class="kwrd">public</span> PagedList( IEnumerable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alt"><span class="lnum">  21:</span>         {</pre>
<pre class="alteven"><span class="lnum">  22:</span>             <span class="kwrd">if</span>( source <span class="kwrd">is</span> IQueryable&lt;T&gt; )</pre>
<pre class="alt"><span class="lnum">  23:</span>                 Initialize( source <span class="kwrd">as</span> IQueryable&lt;T&gt;, index, pageSize );</pre>
<pre class="alteven"><span class="lnum">  24:</span>             <span class="kwrd">else</span></pre>
<pre class="alt"><span class="lnum">  25:</span>                 Initialize( source.AsQueryable(), index, pageSize );</pre>
<pre class="alteven"><span class="lnum">  26:</span>         }</pre>
<pre class="alt"><span class="lnum">  27:</span></pre>
<pre class="alteven"><span class="lnum">  28:</span>         <span class="kwrd">public</span> PagedList( IQueryable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alt"><span class="lnum">  29:</span>         {</pre>
<pre class="alteven"><span class="lnum">  30:</span>             Initialize( source, index, pageSize );</pre>
<pre class="alt"><span class="lnum">  31:</span>         }</pre>
<pre class="alteven"><span class="lnum">  32:</span></pre>
<pre class="alt"><span class="lnum">  33:</span>         <span class="preproc">#region</span> IPagedList Members</pre>
<pre class="alteven"><span class="lnum">  34:</span></pre>
<pre class="alt"><span class="lnum">  35:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> PageCount { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  36:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> TotalItemCount { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  37:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> PageIndex { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  38:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> PageNumber { get { <span class="kwrd">return</span> PageIndex + 1; } }</pre>
<pre class="alt"><span class="lnum">  39:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> PageSize { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  40:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> HasPreviousPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  41:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> HasNextPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  42:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> IsFirstPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  43:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> IsLastPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  44:</span></pre>
<pre class="alt"><span class="lnum">  45:</span>         <span class="preproc">#endregion</span></pre>
<pre class="alteven"><span class="lnum">  46:</span></pre>
<pre class="alt"><span class="lnum">  47:</span>         <span class="kwrd">protected</span> <span class="kwrd">void</span> Initialize( IQueryable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alteven"><span class="lnum">  48:</span>         {</pre>
<pre class="alt"><span class="lnum">  49:</span>             <span class="rem">//### set source to blank list if source is null to prevent exceptions</span></pre>
<pre class="alteven"><span class="lnum">  50:</span>             <span class="kwrd">if</span>( source == <span class="kwrd">null</span> )</pre>
<pre class="alt"><span class="lnum">  51:</span>                 source = <span class="kwrd">new</span> List&lt;T&gt;().AsQueryable();</pre>
<pre class="alteven"><span class="lnum">  52:</span></pre>
<pre class="alt"><span class="lnum">  53:</span>             <span class="rem">//### set properties</span></pre>
<pre class="alteven"><span class="lnum">  54:</span>             TotalItemCount = source.Count();</pre>
<pre class="alt"><span class="lnum">  55:</span>             PageSize = pageSize;</pre>
<pre class="alteven"><span class="lnum">  56:</span>             PageIndex = index;</pre>
<pre class="alt"><span class="lnum">  57:</span>             <span class="kwrd">if</span>( TotalItemCount &gt; 0 )</pre>
<pre class="alteven"><span class="lnum">  58:</span>                 PageCount = (<span class="kwrd">int</span>)Math.Ceiling( TotalItemCount / (<span class="kwrd">double</span>)PageSize );</pre>
<pre class="alt"><span class="lnum">  59:</span>             <span class="kwrd">else</span></pre>
<pre class="alteven"><span class="lnum">  60:</span>                 PageCount = 0;</pre>
<pre class="alt"><span class="lnum">  61:</span>             HasPreviousPage = ( PageIndex &gt; 0 );</pre>
<pre class="alteven"><span class="lnum">  62:</span>             HasNextPage = ( PageIndex &lt; ( PageCount - 1 ) );</pre>
<pre class="alt"><span class="lnum">  63:</span>             IsFirstPage = ( PageIndex &lt;= 0 );</pre>
<pre class="alteven"><span class="lnum">  64:</span>             IsLastPage = ( PageIndex &gt;= ( PageCount - 1 ) );</pre>
<pre class="alt"><span class="lnum">  65:</span></pre>
<pre class="alteven"><span class="lnum">  66:</span>             <span class="rem">//### argument checking</span></pre>
<pre class="alt"><span class="lnum">  67:</span>             <span class="kwrd">if</span>( index &lt; 0 )</pre>
<pre class="alteven"><span class="lnum">  68:</span>                 <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentOutOfRangeException( <span class="str">"PageIndex cannot be below 0."</span> );</pre>
<pre class="alt"><span class="lnum">  69:</span>             <span class="kwrd">if</span>( pageSize &lt; 1 )</pre>
<pre class="alteven"><span class="lnum">  70:</span>                 <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentOutOfRangeException( <span class="str">"PageSize cannot be less than 1."</span> );</pre>
<pre class="alt"><span class="lnum">  71:</span></pre>
<pre class="alteven"><span class="lnum">  72:</span>             <span class="rem">//### add items to internal list</span></pre>
<pre class="alt"><span class="lnum">  73:</span>             <span class="kwrd">if</span>( TotalItemCount &gt; 0 )</pre>
<pre class="alteven"><span class="lnum">  74:</span>                 AddRange( source.Skip( ( index ) * pageSize ).Take( pageSize ).ToList() );</pre>
<pre class="alt"><span class="lnum">  75:</span>         }</pre>
<pre class="alteven"><span class="lnum">  76:</span>     }</pre>
<pre class="alt"><span class="lnum">  77:</span></pre>
<pre class="alteven"><span class="lnum">  78:</span>     <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> Pagination</pre>
<pre class="alt"><span class="lnum">  79:</span>     {</pre>
<pre class="alteven"><span class="lnum">  80:</span>         <span class="kwrd">public</span> <span class="kwrd">static</span> PagedList&lt;T&gt; ToPagedList&lt;T&gt;( <span class="kwrd">this</span> IQueryable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alt"><span class="lnum">  81:</span>         {</pre>
<pre class="alteven"><span class="lnum">  82:</span>             <span class="kwrd">return</span> <span class="kwrd">new</span> PagedList&lt;T&gt;( source, index, pageSize );</pre>
<pre class="alt"><span class="lnum">  83:</span>         }</pre>
<pre class="alteven"><span class="lnum">  84:</span></pre>
<pre class="alt"><span class="lnum">  85:</span>         <span class="kwrd">public</span> <span class="kwrd">static</span> PagedList&lt;T&gt; ToPagedList&lt;T&gt;( <span class="kwrd">this</span> IEnumerable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alteven"><span class="lnum">  86:</span>         {</pre>
<pre class="alt"><span class="lnum">  87:</span>             <span class="kwrd">return</span> <span class="kwrd">new</span> PagedList&lt;T&gt;( source, index, pageSize );</pre>
<pre class="alteven"><span class="lnum">  88:</span>         }</pre>
<pre class="alt"><span class="lnum">  89:</span>     }</pre>
<pre class="alteven"><span class="lnum">  90:</span> }</pre>
</div>
</div>
<p><strong>Changes Since Previous Version:</strong></p>
<ul>
<li><strong>Changed &#8220;TotalPages&#8221; property to &#8220;PageCount&#8221;.</strong>This was done to more clearly illustrate the purpose of this property (more in line with the standard List&lt;T&gt; .Count property).</li>
<li><strong>Changed &#8220;TotalCount&#8221; property to &#8220;TotalItemCount&#8221;.</strong>This was done to differentiate between Pages and Items more clearly.</li>
<li><strong>Switched &#8220;PageIndex&#8221; back to being a zero-based index, rather than one-based.</strong>The PageIndex was set to be one-based because the most common use-case that I could think of, outputting a pager (i.e.: Previous &#8211; 1 &#8211; 2 &#8211; 3 &#8211; Next), was one-based and it would be nice to not have to do &#8220;obj.PageIndex + 1&#8243; everywhere. This was probably a poor decision. <a href="http://www.squaredroot.com/post/2008/04/08/Updated-PagedList-Class.aspx#Comment461b6250-c750-401c-ac1a-2c2553f71b07">Some people found it confusing</a> and <a href="http://www.squaredroot.com/post/2008/04/08/Updated-PagedList-Class.aspx#Commentb2de6623-09a2-49c8-a4e9-d1386a515149">others found that it didn&#8217;t work with the standard .Net DataPager</a>.</li>
<li><strong>Added &#8220;PageNumber&#8221; property.</strong>As suggested <a href="http://www.squaredroot.com/post/2008/04/08/Updated-PagedList-Class.aspx#Comment461b6250-c750-401c-ac1a-2c2553f71b07">via comment</a> on my previous post, PageNumber is just PageIndex + 1.</li>
<li><strong>Treat all data as IQueryable for the duration of class initialization.</strong>Tgmdbm, a frequent contributer on the <a href="http://forums.asp.net/1146.aspx">ASP.Net MVC forums</a>, pointed out <a href="http://www.squaredroot.com/post/2008/04/08/Updated-PagedList-Class.aspx#Comment3d607a04-447c-4113-a42f-33d49f8f8fbd">some good reasons</a> why everything should be treated as IQueryable before the .Skip(x).Take(y). I&#8217;m not 100% sold that treating it as IEnumerable would also work for IQueryable objects (since IQueryable supports IEnumerable), but to be safe I have defaulted everything to using IQueryable. You can still pass in a strict IEnumerable, but it will be converted to IQueryable for the duration of the PagedList class initialization process.</li>
<li><strong>Tested with <a href="http://www.codeplex.com/xunit">xUnit.net</a>.</strong>While the PagedList class isn&#8217;t exactly rocket science, I want to strive to improve the quality of the code that I&#8217;m presenting to the community. I also enjoyed having an excuse to try out xUnit&#8217;s data-driven testing using the [Theory] attribute (similar to MbUnit&#8217;s [RowTest]) for the first time. Not much has been written about it, but I was able to find <a href="http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html">some examples from Ben Hall</a> which got me up and testing quickly.</li>
</ul>
<p>Here is the test class:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">using</span> System;</pre>
<pre class="alteven"><span class="lnum">   2:</span> <span class="kwrd">using</span> System.Collections.Generic;</pre>
<pre class="alt"><span class="lnum">   3:</span> <span class="kwrd">using</span> Xunit;</pre>
<pre class="alteven"><span class="lnum">   4:</span> <span class="kwrd">using</span> XunitExt;</pre>
<pre class="alt"><span class="lnum">   5:</span></pre>
<pre class="alteven"><span class="lnum">   6:</span> <span class="kwrd">namespace</span> SquaredRoot.Collections.Generic.Tests</pre>
<pre class="alt"><span class="lnum">   7:</span> {</pre>
<pre class="alteven"><span class="lnum">   8:</span>     <span class="kwrd">public</span> <span class="kwrd">class</span> PagedListFacts</pre>
<pre class="alt"><span class="lnum">   9:</span>     {</pre>
<pre class="alteven"><span class="lnum">  10:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum">  11:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Null_Data_Set_Doesnt_Throw_Exception()</pre>
<pre class="alteven"><span class="lnum">  12:</span>         {</pre>
<pre class="alt"><span class="lnum">  13:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum">  14:</span>             Assert.ThrowsDelegate act = () =&gt; <span class="kwrd">new</span> PagedList&lt;<span class="kwrd">object</span>&gt;( <span class="kwrd">null</span>, 0, 10 );</pre>
<pre class="alt"><span class="lnum">  15:</span></pre>
<pre class="alteven"><span class="lnum">  16:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum">  17:</span>             Assert.DoesNotThrow( act );</pre>
<pre class="alteven"><span class="lnum">  18:</span>         }</pre>
<pre class="alt"><span class="lnum">  19:</span></pre>
<pre class="alteven"><span class="lnum">  20:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum">  21:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> PageIndex_Below_Zero_Throws_ArgumentOutOfRange()</pre>
<pre class="alteven"><span class="lnum">  22:</span>         {</pre>
<pre class="alt"><span class="lnum">  23:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum">  24:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3 };</pre>
<pre class="alt"><span class="lnum">  25:</span></pre>
<pre class="alteven"><span class="lnum">  26:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum">  27:</span>             Assert.ThrowsDelegate act = () =&gt; data.ToPagedList( -1, 1 );</pre>
<pre class="alteven"><span class="lnum">  28:</span></pre>
<pre class="alt"><span class="lnum">  29:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum">  30:</span>             Assert.Throws&lt;ArgumentOutOfRangeException&gt;( act );</pre>
<pre class="alt"><span class="lnum">  31:</span>         }</pre>
<pre class="alteven"><span class="lnum">  32:</span></pre>
<pre class="alt"><span class="lnum">  33:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum">  34:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> PageIndex_Above_RecordCount_Returns_Empty_List()</pre>
<pre class="alt"><span class="lnum">  35:</span>         {</pre>
<pre class="alteven"><span class="lnum">  36:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum">  37:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3 };</pre>
<pre class="alteven"><span class="lnum">  38:</span></pre>
<pre class="alt"><span class="lnum">  39:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum">  40:</span>             var pagedList = data.ToPagedList( 2, 3 );</pre>
<pre class="alt"><span class="lnum">  41:</span></pre>
<pre class="alteven"><span class="lnum">  42:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum">  43:</span>             Assert.Equal( 0, pagedList.Count );</pre>
<pre class="alteven"><span class="lnum">  44:</span>         }</pre>
<pre class="alt"><span class="lnum">  45:</span></pre>
<pre class="alteven"><span class="lnum">  46:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum">  47:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> PageSize_Below_One_Throws_ArgumentOutOfRange()</pre>
<pre class="alteven"><span class="lnum">  48:</span>         {</pre>
<pre class="alt"><span class="lnum">  49:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum">  50:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3 };</pre>
<pre class="alt"><span class="lnum">  51:</span></pre>
<pre class="alteven"><span class="lnum">  52:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum">  53:</span>             Assert.ThrowsDelegate act = () =&gt; data.ToPagedList( 0, 0 );</pre>
<pre class="alteven"><span class="lnum">  54:</span></pre>
<pre class="alt"><span class="lnum">  55:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum">  56:</span>             Assert.Throws&lt;ArgumentOutOfRangeException&gt;( act );</pre>
<pre class="alt"><span class="lnum">  57:</span>         }</pre>
<pre class="alteven"><span class="lnum">  58:</span></pre>
<pre class="alt"><span class="lnum">  59:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum">  60:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Null_Data_Set_Doesnt_Return_Null()</pre>
<pre class="alt"><span class="lnum">  61:</span>         {</pre>
<pre class="alteven"><span class="lnum">  62:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum">  63:</span>             var pagedList = <span class="kwrd">new</span> PagedList&lt;<span class="kwrd">object</span>&gt;( <span class="kwrd">null</span>, 0, 10 );</pre>
<pre class="alteven"><span class="lnum">  64:</span></pre>
<pre class="alt"><span class="lnum">  65:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum">  66:</span>             Assert.NotNull( pagedList );</pre>
<pre class="alt"><span class="lnum">  67:</span>         }</pre>
<pre class="alteven"><span class="lnum">  68:</span></pre>
<pre class="alt"><span class="lnum">  69:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum">  70:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Null_Data_Set_Returns_Zero_Pages()</pre>
<pre class="alt"><span class="lnum">  71:</span>         {</pre>
<pre class="alteven"><span class="lnum">  72:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum">  73:</span>             var pagedList = <span class="kwrd">new</span> PagedList&lt;<span class="kwrd">object</span>&gt;( <span class="kwrd">null</span>, 0, 10 );</pre>
<pre class="alteven"><span class="lnum">  74:</span></pre>
<pre class="alt"><span class="lnum">  75:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum">  76:</span>             Assert.Equal( 0, pagedList.PageCount );</pre>
<pre class="alt"><span class="lnum">  77:</span>         }</pre>
<pre class="alteven"><span class="lnum">  78:</span></pre>
<pre class="alt"><span class="lnum">  79:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum">  80:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Zero_Item_Data_Set_Returns_Zero_Pages()</pre>
<pre class="alt"><span class="lnum">  81:</span>         {</pre>
<pre class="alteven"><span class="lnum">  82:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum">  83:</span>             var data = <span class="kwrd">new</span> List&lt;<span class="kwrd">object</span>&gt;();</pre>
<pre class="alteven"><span class="lnum">  84:</span></pre>
<pre class="alt"><span class="lnum">  85:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum">  86:</span>             var pagedList = data.ToPagedList( 0, 10 );</pre>
<pre class="alt"><span class="lnum">  87:</span></pre>
<pre class="alteven"><span class="lnum">  88:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum">  89:</span>             Assert.Equal( 0, pagedList.PageCount );</pre>
<pre class="alteven"><span class="lnum">  90:</span>         }</pre>
<pre class="alt"><span class="lnum">  91:</span></pre>
<pre class="alteven"><span class="lnum">  92:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum">  93:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> DataSet_Of_One_Through_Five_PageSize_Of_Two_PageIndex_Of_One_First_Item_Is_Three()</pre>
<pre class="alteven"><span class="lnum">  94:</span>         {</pre>
<pre class="alt"><span class="lnum">  95:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum">  96:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3, 4, 5 };</pre>
<pre class="alt"><span class="lnum">  97:</span></pre>
<pre class="alteven"><span class="lnum">  98:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum">  99:</span>             var pagedList = data.ToPagedList( 1, 2 );</pre>
<pre class="alteven"><span class="lnum"> 100:</span></pre>
<pre class="alt"><span class="lnum"> 101:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 102:</span>             Assert.Equal( 3, pagedList[0] );</pre>
<pre class="alt"><span class="lnum"> 103:</span>         }</pre>
<pre class="alteven"><span class="lnum"> 104:</span></pre>
<pre class="alt"><span class="lnum"> 105:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum"> 106:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> TotalCount_Is_Preserved()</pre>
<pre class="alt"><span class="lnum"> 107:</span>         {</pre>
<pre class="alteven"><span class="lnum"> 108:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum"> 109:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3, 4, 5 };</pre>
<pre class="alteven"><span class="lnum"> 110:</span></pre>
<pre class="alt"><span class="lnum"> 111:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum"> 112:</span>             var pagedList = data.ToPagedList( 1, 2 );</pre>
<pre class="alt"><span class="lnum"> 113:</span></pre>
<pre class="alteven"><span class="lnum"> 114:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum"> 115:</span>             Assert.Equal( 5, pagedList.TotalItemCount );</pre>
<pre class="alteven"><span class="lnum"> 116:</span>         }</pre>
<pre class="alt"><span class="lnum"> 117:</span></pre>
<pre class="alteven"><span class="lnum"> 118:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum"> 119:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> PageIndex_Is_Preserved()</pre>
<pre class="alteven"><span class="lnum"> 120:</span>         {</pre>
<pre class="alt"><span class="lnum"> 121:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum"> 122:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3, 4, 5 };</pre>
<pre class="alt"><span class="lnum"> 123:</span></pre>
<pre class="alteven"><span class="lnum"> 124:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum"> 125:</span>             var pagedList = data.ToPagedList( 1, 2 );</pre>
<pre class="alteven"><span class="lnum"> 126:</span></pre>
<pre class="alt"><span class="lnum"> 127:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 128:</span>             Assert.Equal( 1, pagedList.PageIndex );</pre>
<pre class="alt"><span class="lnum"> 129:</span>         }</pre>
<pre class="alteven"><span class="lnum"> 130:</span></pre>
<pre class="alt"><span class="lnum"> 131:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum"> 132:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> PageSize_Is_Preserved()</pre>
<pre class="alt"><span class="lnum"> 133:</span>         {</pre>
<pre class="alteven"><span class="lnum"> 134:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum"> 135:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3, 4, 5 };</pre>
<pre class="alteven"><span class="lnum"> 136:</span></pre>
<pre class="alt"><span class="lnum"> 137:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum"> 138:</span>             var pagedList = data.ToPagedList( 1, 2 );</pre>
<pre class="alt"><span class="lnum"> 139:</span></pre>
<pre class="alteven"><span class="lnum"> 140:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum"> 141:</span>             Assert.Equal( 2, pagedList.PageSize );</pre>
<pre class="alteven"><span class="lnum"> 142:</span>         }</pre>
<pre class="alt"><span class="lnum"> 143:</span></pre>
<pre class="alteven"><span class="lnum"> 144:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum"> 145:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Data_Is_Filtered_By_PageSize()</pre>
<pre class="alteven"><span class="lnum"> 146:</span>         {</pre>
<pre class="alt"><span class="lnum"> 147:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum"> 148:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3, 4, 5 };</pre>
<pre class="alt"><span class="lnum"> 149:</span></pre>
<pre class="alteven"><span class="lnum"> 150:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum"> 151:</span>             var pagedList = data.ToPagedList( 1, 2 );</pre>
<pre class="alteven"><span class="lnum"> 152:</span></pre>
<pre class="alt"><span class="lnum"> 153:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 154:</span>             Assert.Equal( 2, pagedList.Count );</pre>
<pre class="alt"><span class="lnum"> 155:</span></pre>
<pre class="alteven"><span class="lnum"> 156:</span>             <span class="rem">//### related test below</span></pre>
<pre class="alt"><span class="lnum"> 157:</span></pre>
<pre class="alteven"><span class="lnum"> 158:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum"> 159:</span>             pagedList = data.ToPagedList( 2, 2 );</pre>
<pre class="alteven"><span class="lnum"> 160:</span></pre>
<pre class="alt"><span class="lnum"> 161:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 162:</span>             Assert.Equal( 1, pagedList.Count );</pre>
<pre class="alt"><span class="lnum"> 163:</span>         }</pre>
<pre class="alteven"><span class="lnum"> 164:</span></pre>
<pre class="alt"><span class="lnum"> 165:</span>         [Fact]</pre>
<pre class="alteven"><span class="lnum"> 166:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> DataSet_OneThroughThree_PageSize_One_PageIndex_Two_HasNextPage_False()</pre>
<pre class="alt"><span class="lnum"> 167:</span>         {</pre>
<pre class="alteven"><span class="lnum"> 168:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum"> 169:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3 };</pre>
<pre class="alteven"><span class="lnum"> 170:</span></pre>
<pre class="alt"><span class="lnum"> 171:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum"> 172:</span>             var pagedList = data.ToPagedList( 2, 1 );</pre>
<pre class="alt"><span class="lnum"> 173:</span></pre>
<pre class="alteven"><span class="lnum"> 174:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum"> 175:</span>             Assert.Equal( <span class="kwrd">false</span>, pagedList.HasNextPage );</pre>
<pre class="alteven"><span class="lnum"> 176:</span>         }</pre>
<pre class="alt"><span class="lnum"> 177:</span></pre>
<pre class="alteven"><span class="lnum"> 178:</span>         [Fact]</pre>
<pre class="alt"><span class="lnum"> 179:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> DataSet_OneThroughThree_PageSize_One_PageIndex_Two_IsLastPage_True()</pre>
<pre class="alteven"><span class="lnum"> 180:</span>         {</pre>
<pre class="alt"><span class="lnum"> 181:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum"> 182:</span>             var data = <span class="kwrd">new</span>[]{ 1, 2, 3 };</pre>
<pre class="alt"><span class="lnum"> 183:</span></pre>
<pre class="alteven"><span class="lnum"> 184:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum"> 185:</span>             var pagedList = data.ToPagedList( 2, 1 );</pre>
<pre class="alteven"><span class="lnum"> 186:</span></pre>
<pre class="alt"><span class="lnum"> 187:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 188:</span>             Assert.Equal( <span class="kwrd">true</span>, pagedList.IsLastPage );</pre>
<pre class="alt"><span class="lnum"> 189:</span>         }</pre>
<pre class="alteven"><span class="lnum"> 190:</span></pre>
<pre class="alt"><span class="lnum"> 191:</span>         [Theory]</pre>
<pre class="alteven"><span class="lnum"> 192:</span>         [InlineData( <span class="kwrd">new</span>[] { 1, 2, 3 }, 0, 1 )]</pre>
<pre class="alt"><span class="lnum"> 193:</span>         [InlineData( <span class="kwrd">new</span>[] { 1, 2, 3 }, 1, 2 )]</pre>
<pre class="alteven"><span class="lnum"> 194:</span>         [InlineData( <span class="kwrd">new</span>[] { 1, 2, 3 }, 2, 3 )]</pre>
<pre class="alt"><span class="lnum"> 195:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Theory_PageNumber_Is_PageIndex_Plus_One( <span class="kwrd">int</span>[] integers, <span class="kwrd">int</span> pageIndex, <span class="kwrd">int</span> expectedPageNumber )</pre>
<pre class="alteven"><span class="lnum"> 196:</span>         {</pre>
<pre class="alt"><span class="lnum"> 197:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum"> 198:</span>             var data = integers;</pre>
<pre class="alt"><span class="lnum"> 199:</span></pre>
<pre class="alteven"><span class="lnum"> 200:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum"> 201:</span>             var pagedList = data.ToPagedList( pageIndex, 1 );</pre>
<pre class="alteven"><span class="lnum"> 202:</span></pre>
<pre class="alt"><span class="lnum"> 203:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 204:</span>             Assert.Equal( expectedPageNumber, pagedList.PageNumber );</pre>
<pre class="alt"><span class="lnum"> 205:</span>         }</pre>
<pre class="alteven"><span class="lnum"> 206:</span></pre>
<pre class="alt"><span class="lnum"> 207:</span>         [Theory]</pre>
<pre class="alteven"><span class="lnum"> 208:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 0, 1, <span class="kwrd">false</span>, <span class="kwrd">true</span> )]</pre>
<pre class="alt"><span class="lnum"> 209:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 1, 1, <span class="kwrd">true</span>, <span class="kwrd">true</span> )]</pre>
<pre class="alteven"><span class="lnum"> 210:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 2, 1, <span class="kwrd">true</span>, <span class="kwrd">false</span> )]</pre>
<pre class="alt"><span class="lnum"> 211:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Theory_HasPreviousPage_And_HasNextPage_Are_Correct( <span class="kwrd">int</span>[] integers, <span class="kwrd">int</span> pageIndex, <span class="kwrd">int</span> pageSize, <span class="kwrd">bool</span> expectedHasPrevious, <span class="kwrd">bool</span> expectedHasNext )</pre>
<pre class="alteven"><span class="lnum"> 212:</span>         {</pre>
<pre class="alt"><span class="lnum"> 213:</span>             <span class="rem">//arrange</span></pre>
<pre class="alteven"><span class="lnum"> 214:</span>             var data = integers;</pre>
<pre class="alt"><span class="lnum"> 215:</span></pre>
<pre class="alteven"><span class="lnum"> 216:</span>             <span class="rem">//act</span></pre>
<pre class="alt"><span class="lnum"> 217:</span>             var pagedList = data.ToPagedList( pageIndex, pageSize );</pre>
<pre class="alteven"><span class="lnum"> 218:</span></pre>
<pre class="alt"><span class="lnum"> 219:</span>             <span class="rem">//assert</span></pre>
<pre class="alteven"><span class="lnum"> 220:</span>             Assert.Equal( expectedHasPrevious, pagedList.HasPreviousPage );</pre>
<pre class="alt"><span class="lnum"> 221:</span>             Assert.Equal( expectedHasNext, pagedList.HasNextPage );</pre>
<pre class="alteven"><span class="lnum"> 222:</span>         }</pre>
<pre class="alt"><span class="lnum"> 223:</span></pre>
<pre class="alteven"><span class="lnum"> 224:</span>         [Theory]</pre>
<pre class="alt"><span class="lnum"> 225:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 0, 1, <span class="kwrd">true</span>, <span class="kwrd">false</span> )]</pre>
<pre class="alteven"><span class="lnum"> 226:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 1, 1, <span class="kwrd">false</span>, <span class="kwrd">false</span> )]</pre>
<pre class="alt"><span class="lnum"> 227:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 2, 1, <span class="kwrd">false</span>, <span class="kwrd">true</span> )]</pre>
<pre class="alteven"><span class="lnum"> 228:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Theory_IsFirstPage_And_IsLastPage_Are_Correct( <span class="kwrd">int</span>[] integers, <span class="kwrd">int</span> pageIndex, <span class="kwrd">int</span> pageSize, <span class="kwrd">bool</span> expectedIsFirstPage, <span class="kwrd">bool</span> expectedIsLastPage )</pre>
<pre class="alt"><span class="lnum"> 229:</span>         {</pre>
<pre class="alteven"><span class="lnum"> 230:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum"> 231:</span>             var data = integers;</pre>
<pre class="alteven"><span class="lnum"> 232:</span></pre>
<pre class="alt"><span class="lnum"> 233:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum"> 234:</span>             var pagedList = data.ToPagedList( pageIndex, pageSize );</pre>
<pre class="alt"><span class="lnum"> 235:</span></pre>
<pre class="alteven"><span class="lnum"> 236:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum"> 237:</span>             Assert.Equal( expectedIsFirstPage, pagedList.IsFirstPage );</pre>
<pre class="alteven"><span class="lnum"> 238:</span>             Assert.Equal( expectedIsLastPage, pagedList.IsLastPage );</pre>
<pre class="alt"><span class="lnum"> 239:</span>         }</pre>
<pre class="alteven"><span class="lnum"> 240:</span></pre>
<pre class="alt"><span class="lnum"> 241:</span>         [Theory]</pre>
<pre class="alteven"><span class="lnum"> 242:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 1, 3 )]</pre>
<pre class="alt"><span class="lnum"> 243:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 3, 1 )]</pre>
<pre class="alteven"><span class="lnum"> 244:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1 }, 1, 1 )]</pre>
<pre class="alt"><span class="lnum"> 245:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3 }, 2, 2 )]</pre>
<pre class="alteven"><span class="lnum"> 246:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3, 4 }, 2, 2 )]</pre>
<pre class="alt"><span class="lnum"> 247:</span>         [InlineData( <span class="kwrd">new</span>[]{ 1, 2, 3, 4, 5 }, 2, 3 )]</pre>
<pre class="alteven"><span class="lnum"> 248:</span>         <span class="kwrd">public</span> <span class="kwrd">void</span> Theory_PageCount_Is_Correct( <span class="kwrd">int</span>[] integers, <span class="kwrd">int</span> pageSize, <span class="kwrd">int</span> expectedNumberOfPages )</pre>
<pre class="alt"><span class="lnum"> 249:</span>         {</pre>
<pre class="alteven"><span class="lnum"> 250:</span>             <span class="rem">//arrange</span></pre>
<pre class="alt"><span class="lnum"> 251:</span>             var data = integers;</pre>
<pre class="alteven"><span class="lnum"> 252:</span></pre>
<pre class="alt"><span class="lnum"> 253:</span>             <span class="rem">//act</span></pre>
<pre class="alteven"><span class="lnum"> 254:</span>             var pagedList = data.ToPagedList( 0, pageSize );</pre>
<pre class="alt"><span class="lnum"> 255:</span></pre>
<pre class="alteven"><span class="lnum"> 256:</span>             <span class="rem">//assert</span></pre>
<pre class="alt"><span class="lnum"> 257:</span>             Assert.Equal( expectedNumberOfPages, pagedList.PageCount );</pre>
<pre class="alteven"><span class="lnum"> 258:</span>         }</pre>
<pre class="alt"><span class="lnum"> 259:</span>     }</pre>
<pre class="alteven"><span class="lnum"> 260:</span> }</pre>
</div>
</div>
<p>A big thanks to everyone who has thrown their two cents in to help improve this small but useful class! </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/07/08/pagedlist-strikes-back/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>OpenID Check_Authentication In C#</title>
		<link>http://www.squaredroot.com/2008/04/11/openid-check_authentication/</link>
		<comments>http://www.squaredroot.com/2008/04/11/openid-check_authentication/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 04:01:03 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[OpenID]]></category>

		<guid isPermaLink="false">/post/2008/04/11/OpenID-Check_Authentication.aspx</guid>
		<description><![CDATA[Earlier this year Mads Krisensen (of BlogEngine.net fame) posted a lightweight implementation of OpenID using C#. In the comments on Mads&#8217; post, Andrew Arnott (a developer of the DotNetOpenId library) mentioned that the example Mads had posted could &#34;be hacked with a single change of a word in the URL.&#34; This is what is technically [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this year Mads Krisensen (of <a href="http://www.dotnetblogengine.net/">BlogEngine.net</a> fame) posted a <a href="http://blog.madskristensen.dk/post/OpenID-implementation-in-Csharp-and-ASPNET.aspx">lightweight implementation of OpenID</a> using C#. In the comments on Mads&#8217; post, <a href="http://blog.nerdbank.net/">Andrew Arnott</a> (<a href="http://blog.nerdbank.net/2008/04/dotnetopenid-2.html">a developer of the DotNetOpenId library</a>) mentioned that the example Mads had posted could &quot;be hacked with a single change of a word in the URL.&quot; This is what is technically referred to as a <strong>Very Bad Thing</strong>. Andrew and another poster named &quot;neil&quot; went on to elaborate that implementing OpenID&#8217;s &quot;check_authentication&quot; algorithm would close this security hole. Unfortunately as of the writing of this article neither Mads nor any of the commentors have provided an implementation of check_authentication that works with the class Mads posted (bear in mind that Andrew only brought up this issue less than a week ago, so Mads may very well be working on it).</p>
<p>Fast forward to yesterday when I was researching my options for implementing OpenID for the next release of the <a href="http://www.codeplex.com/MvcMembership">ASP.Net MVC Membership Starter Kit</a>. I liked Mads solution more than the other OpenID libraries that are current available because of its brevity and how easy it is to include it in a project without introducing an extra assembly dependency, so I decided to go ahead and add the check_authentication functionality. A quick read of <a href="http://openid.net/specs/openid-authentication-1_1.html#mode_check_authentication">that portion of the OpenID spec</a> and a couple hours of coding/testing and I think I&#8217;m about finished.</p>
<p>Here is the method you need to add to Mads&#8217; class:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> CheckAuthentication( NameValueCollection query )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">   4:</span>     <span class="rem">//### get data required for check_authentication</span></pre>
<pre class="alt"><span class="lnum">   5:</span>     <span class="kwrd">string</span> mode = <span class="str">&quot;check_authentication&quot;</span>;</pre>
<pre class="alteven"><span class="lnum">   6:</span>     <span class="kwrd">string</span> handle = query[<span class="str">&quot;openid.assoc_handle&quot;</span>];</pre>
<pre class="alt"><span class="lnum">   7:</span>     <span class="kwrd">string</span> signature = query[<span class="str">&quot;openid.sig&quot;</span>];</pre>
<pre class="alteven"><span class="lnum">   8:</span>     <span class="kwrd">string</span> signed = query[<span class="str">&quot;openid.signed&quot;</span>];</pre>
<pre class="alt"><span class="lnum">   9:</span>     <span class="kwrd">string</span> extra = <span class="kwrd">string</span>.Empty;</pre>
<pre class="alteven"><span class="lnum">  10:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  11:</span>     <span class="rem">//### loop through fields required by &quot;openid.signed&quot; and retrieve that data</span></pre>
<pre class="alteven"><span class="lnum">  12:</span>     <span class="kwrd">if</span>( !<span class="kwrd">string</span>.IsNullOrEmpty(signed) )</pre>
<pre class="alt"><span class="lnum">  13:</span>     {</pre>
<pre class="alteven"><span class="lnum">  14:</span>         <span class="kwrd">string</span>[] exemptions = { <span class="str">&quot;mode&quot;</span>, <span class="str">&quot;assoc_handle&quot;</span>, <span class="str">&quot;sig&quot;</span>, <span class="str">&quot;signed&quot;</span> };</pre>
<pre class="alt"><span class="lnum">  15:</span>         <span class="kwrd">string</span>[] fields = signed.Split(<span class="str">','</span>);</pre>
<pre class="alteven"><span class="lnum">  16:</span>         <span class="kwrd">foreach</span>( <span class="kwrd">string</span> field <span class="kwrd">in</span> fields )</pre>
<pre class="alt"><span class="lnum">  17:</span>         {</pre>
<pre class="alteven"><span class="lnum">  18:</span>             <span class="kwrd">if</span>( exemptions.Contains(field) ) <span class="kwrd">continue</span>;</pre>
<pre class="alt"><span class="lnum">  19:</span>             extra += <span class="kwrd">string</span>.Format( <span class="str">&quot;openid.{0}={1}&amp;&quot;</span>, field, HttpUtility.UrlEncode( query[ <span class="str">&quot;openid.&quot;</span> + field ] ) );</pre>
<pre class="alteven"><span class="lnum">  20:</span>         }</pre>
<pre class="alt"><span class="lnum">  21:</span>         extra = <span class="str">&quot;&amp;&quot;</span> + extra.Substring( 0, extra.Length - 1 );</pre>
<pre class="alteven"><span class="lnum">  22:</span>     }</pre>
<pre class="alt"><span class="lnum">  23:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">  24:</span>     <span class="rem">//### combine all the data together to form the request</span></pre>
<pre class="alt"><span class="lnum">  25:</span>     <span class="kwrd">string</span> post = <span class="kwrd">string</span>.Format( <span class="str">&quot;openid.mode={0}&amp;openid.assoc_handle={1}&amp;openid.sig={2}&amp;openid.signed={3}{4}&quot;</span>,</pre>
<pre class="alteven"><span class="lnum">  26:</span>         mode,</pre>
<pre class="alt"><span class="lnum">  27:</span>         HttpUtility.UrlEncode( handle ),</pre>
<pre class="alteven"><span class="lnum">  28:</span>         HttpUtility.UrlEncode( signature ),</pre>
<pre class="alt"><span class="lnum">  29:</span>         HttpUtility.UrlEncode( signed ),</pre>
<pre class="alteven"><span class="lnum">  30:</span>         extra</pre>
<pre class="alt"><span class="lnum">  31:</span>     );</pre>
<pre class="alteven"><span class="lnum">  32:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  33:</span>     <span class="rem">//### begin sending request</span></pre>
<pre class="alteven"><span class="lnum">  34:</span>     HttpWebRequest request = (HttpWebRequest)WebRequest.Create( query[<span class="str">&quot;openid.op_endpoint&quot;</span>] );</pre>
<pre class="alt"><span class="lnum">  35:</span>     request.Method = <span class="str">&quot;POST&quot;</span>;</pre>
<pre class="alteven"><span class="lnum">  36:</span>     request.ContentType = <span class="str">&quot;application/x-www-form-urlencoded&quot;</span>;</pre>
<pre class="alt"><span class="lnum">  37:</span>     request.ContentLength = post.Length;</pre>
<pre class="alteven"><span class="lnum">  38:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  39:</span>     <span class="rem">//### transmit POST data</span></pre>
<pre class="alteven"><span class="lnum">  40:</span>     <span class="kwrd">using</span>( StreamWriter sw = <span class="kwrd">new</span> StreamWriter(request.GetRequestStream()) )</pre>
<pre class="alt"><span class="lnum">  41:</span>         sw.Write(post);</pre>
<pre class="alteven"><span class="lnum">  42:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  43:</span>     <span class="rem">//### get response</span></pre>
<pre class="alteven"><span class="lnum">  44:</span>     <span class="kwrd">string</span> html = <span class="str">&quot;&quot;</span>;</pre>
<pre class="alt"><span class="lnum">  45:</span>     <span class="kwrd">using</span>( HttpWebResponse response = (HttpWebResponse)request.GetResponse() )</pre>
<pre class="alteven"><span class="lnum">  46:</span>         <span class="kwrd">using</span>( StreamReader sr = <span class="kwrd">new</span> StreamReader( response.GetResponseStream() ) )</pre>
<pre class="alt"><span class="lnum">  47:</span>             html = sr.ReadToEnd();</pre>
<pre class="alteven"><span class="lnum">  48:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  49:</span>     <span class="rem">//### determine if check_authentication passed or not</span></pre>
<pre class="alteven"><span class="lnum">  50:</span>     <span class="kwrd">if</span>( <span class="kwrd">string</span>.IsNullOrEmpty(html) || !html.StartsWith( <span class="str">&quot;is_valid:&quot;</span> ) || html.StartsWith( <span class="str">&quot;is_valid:false&quot;</span> ) )</pre>
<pre class="alt"><span class="lnum">  51:</span>         <span class="kwrd">return</span> <span class="kwrd">false</span>;</pre>
<pre class="alteven"><span class="lnum">  52:</span>     <span class="kwrd">else</span> <span class="kwrd">if</span>( html.StartsWith( <span class="str">&quot;is_valid:true&quot;</span> ) )</pre>
<pre class="alt"><span class="lnum">  53:</span>         <span class="kwrd">return</span> <span class="kwrd">true</span>;</pre>
<pre class="alteven"><span class="lnum">  54:</span>     <span class="kwrd">else</span></pre>
<pre class="alt"><span class="lnum">  55:</span>         <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException( <span class="str">&quot;Unexpected return from OpenID check_authentication.&quot;</span> );</pre>
<pre class="alteven"><span class="lnum">  56:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  57:</span> }</pre>
</p></div>
</div>
<p>Now you need to make sure that method is called from somewhere. I chose to make the method private and just call it from inside the Authenticate method. Within the Authenticate method replace:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="rem">// Make sure the incoming request's identity matches the one stored in session</span></pre>
<pre class="alteven"><span class="lnum">   2:</span> <span class="kwrd">if</span>( query[<span class="str">&quot;openid.claimed_id&quot;</span>] != data.Identity )</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">return</span> data;</pre>
</p></div>
</div>
<p>&#8230; with&#8230;</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="rem">// Make sure the incoming request's identity matches the one stored in session</span></pre>
<pre class="alteven"><span class="lnum">   2:</span> <span class="kwrd">if</span>( query[<span class="str">&quot;openid.claimed_id&quot;</span>] != data.Identity )</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">return</span> data;</pre>
<pre class="alteven"><span class="lnum">   4:</span> <span class="kwrd">else</span> <span class="kwrd">if</span>( !CheckAuthentication( query ) )</pre>
<pre class="alt"><span class="lnum">   5:</span>     <span class="kwrd">throw</span> <span class="kwrd">new</span> UnauthorizedAccessException( <span class="str">&quot;OpenID False Verification Detected&quot;</span> );</pre>
</p></div>
</div>
<p>And that&#8217;s it!</p>
<p>If anyone with more experience than I in OpenID waters sees a problem with my implementation, let me know and I will try to get it fixed quickly.</p>
<p><strong>NOTE:</strong> I am aware that Mads&#8217; implementation and the use of &#8216;check_authentication&#8217; is considered an overly chatty use of OpenID. It seems to me that the extra complexity required to implement OpenID 2.0 protocol is just not worthwhile for most OpenID consumers. Feel free to let me know why this is a stupid position to take.</p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/04/11/openid-check_authentication/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/04/11/openid-check_authentication/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/04/11/openid-check_authentication/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/04/11/openid-check_authentication/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/04/11/openid-check_authentication/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Rob Conery&#8217;s PagedList Class (Updated)</title>
		<link>http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/</link>
		<comments>http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 01:33:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[paging]]></category>

		<guid isPermaLink="false">/post/2008/04/08/Updated-PagedList-Class.aspx</guid>
		<description><![CDATA[NOTE: A new, improved version of this class is now available at: http://www.squaredroot.com/post/2008/07/08/PagedList-Strikes-Back.aspx Robert Muehsig has posted a great user control for the MVC framework that adds pagination links to the bottom of a paged list. In it he used a slightly customized version of Rob Conery&#8217;s PagedList class that Rob was kind enough to [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><strong>NOTE:</strong>      <br />A new, improved version of this class is now available at:</p>
<p><a title="http://www.squaredroot.com/post/2008/07/08/PagedList-Strikes-Back.aspx" href="http://www.squaredroot.com/post/2008/07/08/PagedList-Strikes-Back.aspx">http://www.squaredroot.com/post/2008/07/08/PagedList-Strikes-Back.aspx</a></p>
</blockquote>
<p>Robert Muehsig has posted a great user control for the MVC framework that <a href="http://code-inside.de/blog-in/2008/04/08/aspnet-mvc-pagination-view-user-control/">adds pagination links to the bottom of a paged list</a>. In it he used a slightly customized version of <a href="http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/">Rob Conery&#8217;s PagedList</a> class that Rob was kind enough to post way back when the first CTP was released. This reminded me that I should probably post the version I have customized, as I think it makes it a bit easier to use and maintain. I&#8217;ve included the code below. </p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">using</span> System;</pre>
<pre class="alteven"><span class="lnum">   2:</span> <span class="kwrd">using</span> System.Linq;</pre>
<pre class="alt"><span class="lnum">   3:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">   4:</span> <span class="kwrd">namespace</span> System.Collections.Generic</pre>
<pre class="alt"><span class="lnum">   5:</span> {</pre>
<pre class="alteven"><span class="lnum">   6:</span>&#160; </pre>
<pre class="alt"><span class="lnum">   7:</span>     <span class="kwrd">public</span> <span class="kwrd">interface</span> IPagedList</pre>
<pre class="alteven"><span class="lnum">   8:</span>     {</pre>
<pre class="alt"><span class="lnum">   9:</span>         <span class="kwrd">int</span> TotalPages { get; }</pre>
<pre class="alteven"><span class="lnum">  10:</span>         <span class="kwrd">int</span> TotalCount { get; }</pre>
<pre class="alt"><span class="lnum">  11:</span>         <span class="kwrd">int</span> PageIndex { get; }</pre>
<pre class="alteven"><span class="lnum">  12:</span>         <span class="kwrd">int</span> PageSize { get; }</pre>
<pre class="alt"><span class="lnum">  13:</span>         <span class="kwrd">bool</span> HasPreviousPage { get; }</pre>
<pre class="alteven"><span class="lnum">  14:</span>         <span class="kwrd">bool</span> HasNextPage { get; }</pre>
<pre class="alt"><span class="lnum">  15:</span>         <span class="kwrd">bool</span> IsFirstPage { get; }</pre>
<pre class="alteven"><span class="lnum">  16:</span>         <span class="kwrd">bool</span> IsLastPage { get; }</pre>
<pre class="alt"><span class="lnum">  17:</span>     }</pre>
<pre class="alteven"><span class="lnum">  18:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  19:</span>     <span class="kwrd">public</span> <span class="kwrd">class</span> PagedList&lt;T&gt; : List&lt;T&gt;, IPagedList</pre>
<pre class="alteven"><span class="lnum">  20:</span>     {</pre>
<pre class="alt"><span class="lnum">  21:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">  22:</span>         <span class="kwrd">public</span> PagedList( IEnumerable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alt"><span class="lnum">  23:</span>         {</pre>
<pre class="alteven"><span class="lnum">  24:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  25:</span>             <span class="rem">//### set source to blank list if source is null to prevent exceptions</span></pre>
<pre class="alteven"><span class="lnum">  26:</span>             <span class="kwrd">if</span>( source == <span class="kwrd">null</span> )</pre>
<pre class="alt"><span class="lnum">  27:</span>                 source = <span class="kwrd">new</span> List&lt;T&gt;();</pre>
<pre class="alteven"><span class="lnum">  28:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  29:</span>             <span class="rem">//### set properties</span></pre>
<pre class="alteven"><span class="lnum">  30:</span>             <span class="kwrd">this</span>.TotalCount = source.Count();</pre>
<pre class="alt"><span class="lnum">  31:</span>             <span class="kwrd">this</span>.PageSize = pageSize;</pre>
<pre class="alteven"><span class="lnum">  32:</span>             <span class="kwrd">this</span>.PageIndex = index;</pre>
<pre class="alt"><span class="lnum">  33:</span>             <span class="kwrd">if</span>( <span class="kwrd">this</span>.TotalCount &gt; 0 )</pre>
<pre class="alteven"><span class="lnum">  34:</span>                 <span class="kwrd">this</span>.TotalPages = (<span class="kwrd">int</span>)Math.Ceiling( (<span class="kwrd">double</span>)<span class="kwrd">this</span>.TotalCount / (<span class="kwrd">double</span>)<span class="kwrd">this</span>.PageSize );</pre>
<pre class="alt"><span class="lnum">  35:</span>             <span class="kwrd">else</span></pre>
<pre class="alteven"><span class="lnum">  36:</span>                 <span class="kwrd">this</span>.TotalPages = 0;</pre>
<pre class="alt"><span class="lnum">  37:</span>             <span class="kwrd">this</span>.HasPreviousPage = ( <span class="kwrd">this</span>.PageIndex &gt; 1 );</pre>
<pre class="alteven"><span class="lnum">  38:</span>             <span class="kwrd">this</span>.HasNextPage = ( <span class="kwrd">this</span>.PageIndex &lt; <span class="kwrd">this</span>.TotalPages );</pre>
<pre class="alt"><span class="lnum">  39:</span>             <span class="kwrd">this</span>.IsFirstPage = ( <span class="kwrd">this</span>.PageIndex == 1 );</pre>
<pre class="alteven"><span class="lnum">  40:</span>             <span class="kwrd">this</span>.IsLastPage = ( <span class="kwrd">this</span>.PageIndex == <span class="kwrd">this</span>.TotalPages );</pre>
<pre class="alt"><span class="lnum">  41:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">  42:</span>             <span class="rem">//### argument checking</span></pre>
<pre class="alt"><span class="lnum">  43:</span>             <span class="kwrd">if</span>( index &lt; 1 || index &gt; <span class="kwrd">this</span>.TotalPages )</pre>
<pre class="alteven"><span class="lnum">  44:</span>                 <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentOutOfRangeException( <span class="str">&quot;PageIndex out of range.&quot;</span> );</pre>
<pre class="alt"><span class="lnum">  45:</span>             <span class="kwrd">if</span>( pageSize &lt; 1 )</pre>
<pre class="alteven"><span class="lnum">  46:</span>                 <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentOutOfRangeException( <span class="str">&quot;PageSize cannot be less than 1.&quot;</span> );</pre>
<pre class="alt"><span class="lnum">  47:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">  48:</span>             <span class="rem">//### add items to internal list</span></pre>
<pre class="alt"><span class="lnum">  49:</span>             <span class="kwrd">if</span>( <span class="kwrd">this</span>.TotalCount &gt; 0 )</pre>
<pre class="alteven"><span class="lnum">  50:</span>                 <span class="kwrd">this</span>.AddRange( source.Skip( ( index - 1 ) * pageSize ).Take( pageSize ).ToList() );</pre>
<pre class="alt"><span class="lnum">  51:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">  52:</span>         }</pre>
<pre class="alt"><span class="lnum">  53:</span>&#160; </pre>
<pre class="alteven"><span class="lnum">  54:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> TotalPages { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  55:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> TotalCount { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  56:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> PageIndex { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  57:</span>         <span class="kwrd">public</span> <span class="kwrd">int</span> PageSize { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  58:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> HasPreviousPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  59:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> HasNextPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  60:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> IsFirstPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alt"><span class="lnum">  61:</span>         <span class="kwrd">public</span> <span class="kwrd">bool</span> IsLastPage { get; <span class="kwrd">private</span> set; }</pre>
<pre class="alteven"><span class="lnum">  62:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  63:</span>     }</pre>
<pre class="alteven"><span class="lnum">  64:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  65:</span>     <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> Pagination</pre>
<pre class="alteven"><span class="lnum">  66:</span>     {</pre>
<pre class="alt"><span class="lnum">  67:</span>         <span class="kwrd">public</span> <span class="kwrd">static</span> PagedList&lt;T&gt; ToPagedList&lt;T&gt;( <span class="kwrd">this</span> IEnumerable&lt;T&gt; source, <span class="kwrd">int</span> index, <span class="kwrd">int</span> pageSize )</pre>
<pre class="alteven"><span class="lnum">  68:</span>         {</pre>
<pre class="alt"><span class="lnum">  69:</span>             <span class="kwrd">return</span> <span class="kwrd">new</span> PagedList&lt;T&gt;( source, index, pageSize );</pre>
<pre class="alteven"><span class="lnum">  70:</span>         }</pre>
<pre class="alt"><span class="lnum">  71:</span>     }</pre>
<pre class="alteven"><span class="lnum">  72:</span>&#160; </pre>
<pre class="alt"><span class="lnum">  73:</span> }</pre>
</p></div>
</div>
<p><strong>Changes from Rob&#8217;s version:</strong> </p>
<ul>
<li><strong>Added a &quot;TotalPages&quot; property.<br />
      <br /></strong>If you&#8217;re going to loop through each of the pages to display page navigation, you&#8217;ll obviously need this. </li>
<li><strong>Changed &quot;IsPreviousPage&quot; to &quot;HasPreviousPage&quot;.<br />
      <br /></strong>It just sounds better. </li>
<li><strong>Changed &quot;IsNextPage&quot; to &quot;HasNextPage&quot;.<br />
      <br /></strong>See above. </li>
<li><strong>Added a &quot;IsFirstPage&quot; property.<br />
      <br /></strong>The opposite way of using the above two properties. I prefer this way, but kept the original way for backwards compatibility (except the naming). </li>
<li><strong>Added a &quot;IsLastPage&quot; property.<br />
      <br /></strong>See above. </li>
<li><strong>Changed the first constructor to accept IEnumerable&lt;T&gt; rather than IQueryable&lt;T&gt;.<br />
      <br /></strong>I&#8217;m not exactly sure why Rob originally made it IQueryable. I&#8217;m aware that by passing an IQueryable (LINQ) object to this constructor you&#8217;ll avoid retrieving the entire set (only taking the results needed), but since IQueryable inherits from IEnumerable everything should be hunky-dory. He probably had a reason and I&#8217;m going to wind up breaking all of my stuff, but IEnumerable is just so much handier. =) </li>
<li><strong>Removed the second constructor.<br />
      <br /></strong>The second constructor took List&lt;T&gt;, which is unnecessary after changing the first constructor to accept IEnumerable. </li>
<li><strong>Cleaned up property declarations a bit.<br />
      <br /></strong>Mainly to make the page a bit shorter, but also to prevent the multiple calculations that could happen in the original. Also the original allowed the changing of certain properties after an instance was created, which would put the instance into an inconsistent state. </li>
<li><strong>Added argument checking and handled a few exception scenarios more gracefully.<br />
      <br /></strong>Trying to make debugging a bit friendlier. </li>
<li><strong>Removed the second extension method that didn&#8217;t specify a pageSize.<br />
      <br /></strong>I don&#8217;t really think that baking in an extension method that sets pageSize to 10 is a good idea, I&#8217;d prefer pageSize to be explicitly set elsewhere by the calling code. </li>
<li><strong>Moved the code to the &quot;System.Collections.Generic&quot; namespace.<br />
      <br /></strong>I&#8217;m sure a lot of you are breaking out in a cold sweat to see me putting something into a System.* namespace, but I kind of feel like this is something that the .Net team just &quot;forgot&quot;. =) Move it wherever makes you comfortable. </li>
</ul>
<p>Please note that I took many of these ideas from the commentary below Rob&#8217;s original post. I&#8217;m sure many of you are using something similar, but I thought it would be useful to get something posted online that is a bit more fleshed out than the original example. </p>
<p>Thanks for the great work Rob &amp; Robert! </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/04/08/updated-pagedlist-class/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Lambdas Using Funcs and Actions</title>
		<link>http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/</link>
		<comments>http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/#comments</comments>
		<pubDate>Tue, 12 Feb 2008 15:46:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[functional programming]]></category>

		<guid isPermaLink="false">/post/2008/02/12/Lambdas-Using-Funcs-and-Actions.aspx</guid>
		<description><![CDATA[Many of you are probably familiar with lambda expressions by now, as they have been extensively covered since the release of .Net 3.5. Most articles tend to focus on how to pass a lambda expression into a method, but how do you create a method that accepts a lambda expression? Enter the Func and Action [...]]]></description>
			<content:encoded><![CDATA[<p>Many of you are probably familiar with <a href="http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-language-feature-lambda-expressions.aspx">lambda expressions</a> by now, as they have been extensively covered since the release of .Net 3.5. Most articles tend to focus on how to pass a lambda expression into a method, but how do you create a method that accepts a lambda expression? Enter the <strong><a href="http://msdn2.microsoft.com/en-us/library/bb549151.aspx">Func</a></strong> and <strong><a href="http://msdn2.microsoft.com/en-us/library/system.action.aspx">Action</a></strong> types&#8230;</p>
<h2>Funcs vs. Actions</h2>
<p><strong>Funcs</strong> and <strong>Actions</strong> are extremely similar; both give you first class support for passing an anonymous method into another method. The difference is in the return value: <strong>Funcs</strong> have one, <strong>Actions</strong> do not.</p>
<h2>A Simple Action Consumer</h2>
<p>There are several variants of the <strong>Action</strong> type, each taking a varying number of generic parameters. The simplest generic <strong>Action</strong> takes one generic parameters: the type of the object to be passed into the <strong>Action</strong>.</p>
<p>Suppose you had a list of articles and wanted to iterate through them and modify each of them in some way, but only the ones that were created before 2008. In this case you should probably use a <strong>foreach</strong> loop, but instead I&#8217;ll show you how to do it by encapsulating that <strong>foreach</strong> loop in another method that then calls your lambda:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> IterateArticles( Action&lt;Article&gt; process, List&lt;Article&gt; articles )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">foreach</span>( Article article <span class="kwrd">in</span> articles )</pre>
<pre class="alteven"><span class="lnum">   4:</span>         <span class="kwrd">if</span>( article.Created.Year &lt; 2008 )</pre>
<pre class="alt"><span class="lnum">   5:</span>             process(article);</pre>
<pre class="alteven"><span class="lnum">   6:</span> }</pre>
<pre class="alt"><span class="lnum">   7:</span></pre>
<pre class="alteven"><span class="lnum">   8:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> ProcessArticles()</pre>
<pre class="alt"><span class="lnum">   9:</span> {</pre>
<pre class="alteven"><span class="lnum">  10:</span>     List&lt;Article&gt; articles = GetArticles();</pre>
<pre class="alt"><span class="lnum">  11:</span>     IterateArticles( x=&gt;{</pre>
<pre class="alteven"><span class="lnum">  12:</span></pre>
<pre class="alt"><span class="lnum">  13:</span>         x.Title = x.Title.Trim();</pre>
<pre class="alteven"><span class="lnum">  14:</span>         x.Category = x.Category.Trim();</pre>
<pre class="alt"><span class="lnum">  15:</span>         x.LastModified = DateTime.Now;</pre>
<pre class="alteven"><span class="lnum">  16:</span></pre>
<pre class="alt"><span class="lnum">  17:</span>     }, articles );</pre>
<pre class="alteven"><span class="lnum">  18:</span> }</pre>
</div>
</div>
<p>I&#8217;ll be the first to admit it isn&#8217;t the finest example of coding practices, but I believe it illustrates how you can use an <strong>Action</strong> to pass processing in as a parameter.</p>
<h2>A Simple Func Consumer</h2>
<p>What if you want to pass in your processing and retrieve a return value? Use the <strong>Func</strong> type. Let&#8217;s keep the same example as above, but this time we&#8217;ll place variable processing in the lambda to manipulate the article&#8217;s title differently based upon the year the article was published:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> IterateArticles( Func&lt;Article,<span class="kwrd">string</span>&gt; process, List&lt;Article&gt; articles )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">foreach</span>( Article article <span class="kwrd">in</span> articles )</pre>
<pre class="alteven"><span class="lnum">   4:</span>         article.Title = process(article);</pre>
<pre class="alt"><span class="lnum">   5:</span> }</pre>
<pre class="alteven"><span class="lnum">   6:</span></pre>
<pre class="alt"><span class="lnum">   7:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> ProcessArticles()</pre>
<pre class="alteven"><span class="lnum">   8:</span> {</pre>
<pre class="alt"><span class="lnum">   9:</span>     List&lt;Article&gt; articles = GetArticles();</pre>
<pre class="alteven"><span class="lnum">  10:</span>     IterateArticles( x=&gt;{</pre>
<pre class="alt"><span class="lnum">  11:</span></pre>
<pre class="alteven"><span class="lnum">  12:</span>         <span class="kwrd">if</span>( x.Created.Year &lt; 2008 )</pre>
<pre class="alt"><span class="lnum">  13:</span>             <span class="kwrd">return</span> x.Title.ToLower();</pre>
<pre class="alteven"><span class="lnum">  14:</span>         <span class="kwrd">else</span></pre>
<pre class="alt"><span class="lnum">  15:</span>             <span class="kwrd">return</span> x.Title.ToUpper();</pre>
<pre class="alteven"><span class="lnum">  16:</span></pre>
<pre class="alt"><span class="lnum">  17:</span>     }, articles );</pre>
<pre class="alteven"><span class="lnum">  18:</span> }</pre>
</div>
</div>
<p>In the above example you&#8217;ll see that we have changed <strong>Action</strong> to <strong>Func</strong> in the <strong>IterateArticles</strong> method signature and that we have added a string to the list of types in the <strong>Func</strong> definition. <em>When using a <strong>Func</strong>, the last generic parameter is always the return type.</em> You should also note that we can now return a value from our anonymous method.</p>
<h2><strong>A Two-Parameter Func</strong></h2>
<p>Finally let&#8217;s take a look at an example of a multi-parameter <strong>Func</strong>. Once again we&#8217;ll use the same example, except this time rather than passing the <strong>Article</strong> object to the anonymous method we&#8217;ll pass only the data it needs: the date created and the title:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> IterateArticles( Func&lt;DateTime,<span class="kwrd">string</span>,<span class="kwrd">string</span>&gt; process, List&lt;Article&gt; articles )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">foreach</span>( Article article <span class="kwrd">in</span> articles )</pre>
<pre class="alteven"><span class="lnum">   4:</span>         article.Title = process( article.Created, article.Title );</pre>
<pre class="alt"><span class="lnum">   5:</span> }</pre>
<pre class="alteven"><span class="lnum">   6:</span></pre>
<pre class="alt"><span class="lnum">   7:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> ProcessArticles()</pre>
<pre class="alteven"><span class="lnum">   8:</span> {</pre>
<pre class="alt"><span class="lnum">   9:</span>     List&lt;Article&gt; articles = GetArticles();</pre>
<pre class="alteven"><span class="lnum">  10:</span>     IterateArticles( (x,y)=&gt;{</pre>
<pre class="alt"><span class="lnum">  11:</span></pre>
<pre class="alteven"><span class="lnum">  12:</span>         <span class="kwrd">if</span>( x.Year &lt; 2008 )</pre>
<pre class="alt"><span class="lnum">  13:</span>             <span class="kwrd">return</span> y.ToLower();</pre>
<pre class="alteven"><span class="lnum">  14:</span>         <span class="kwrd">else</span></pre>
<pre class="alt"><span class="lnum">  15:</span>             <span class="kwrd">return</span> y.ToUpper();</pre>
<pre class="alteven"><span class="lnum">  16:</span></pre>
<pre class="alt"><span class="lnum">  17:</span>     }, articles );</pre>
<pre class="alteven"><span class="lnum">  18:</span> }</pre>
</div>
</div>
<p>Here we have specified three generic parameters for the <strong>Func</strong>; two to be passed in, one to return. In our lambda expression we have also had to wrap the &#8220;x,y&#8221; in parentheses to prevent the compiler from throwing an error because it thinks the comma is intended to separate parameters to the <strong>IterateArticles</strong> method rather than the <strong>Func.</strong></p>
<h2>A Zero-Parameter Func</h2>
<p>Occasionally you may need to use a <strong>Func</strong> that will not require any parameters. Trying to pass this into the lambda consumer using only the &#8220;{&#8230;}&#8221; notation of anonymous methods will not work, you will need to use &#8220;()=&gt;{&#8230;}&#8221; as seen below:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> IterateArticles( Func&lt;<span class="kwrd">string</span>&gt; process, List&lt;Article&gt; articles )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">foreach</span>( Article article <span class="kwrd">in</span> articles )</pre>
<pre class="alteven"><span class="lnum">   4:</span>         article.Title = process();</pre>
<pre class="alt"><span class="lnum">   5:</span> }</pre>
<pre class="alteven"><span class="lnum">   6:</span> <span class="kwrd">public</span> <span class="kwrd">void</span> ProcessArticles()</pre>
<pre class="alt"><span class="lnum">   7:</span> {</pre>
<pre class="alteven"><span class="lnum">   8:</span>     List&lt;Article&gt; articles = GetArticles();</pre>
<pre class="alt"><span class="lnum">   9:</span>     IterateArticles( ()=&gt;{</pre>
<pre class="alteven"><span class="lnum">  10:</span></pre>
<pre class="alt"><span class="lnum">  11:</span>         <span class="kwrd">return</span> <span class="str">"Published on "</span> + DateTime.Now.ToString();</pre>
<pre class="alteven"><span class="lnum">  12:</span></pre>
<pre class="alt"><span class="lnum">  13:</span>     }, articles );</pre>
<pre class="alteven"><span class="lnum">  14:</span> }</pre>
</div>
</div>
<p>I hope this helps get you started creating your own lambda consuming methods. Keep in mind that <strong>Funcs</strong> and <strong>Actions</strong> are not limited to just one or two parameters as shown in this article; both can accept up to four input parameters (not including the <strong>Func&#8217;s</strong> extra return parameter). As you become more comfortable creating lambda expressions and lambda consumers I am certain you will find many places in our your code that can be simplified and/or made more flexible by using them. </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/02/12/lambdas-using-funcs-and-actions/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
