Twitter style paging with ASP.NET MVC and jQuery


I really like the simplicity of the AJAX paging at Twitter so I decided to use the same type of paging, including a similar more button, on the start page on this site. It actually surprised me how simple it was to build it, including fallback for visitors that doesn’t have javascript enabled (such as our dear friend Google), with ASP.NET MVC and a few lines of javascript with jQuery.

Basic controller logic

Being an advocate of progressive enhancement I started out by building a non-AJAX version of the feature. In the controller for the start page I let the default (Index) method have a nullable int parameter named entryCount which tells the method how many of the latest blog entries it should return for the view to display.

public class HomeController : Controller


private const int defaultEntryCount = 10;

public ActionResult Index(int? entryCount)


if (!entryCount.HasValue)
entryCount = defaultEntryCount;
//Retrieve the first page with a page size of entryCount
int totalItems;
IEnumerable<Entry> entries = GetLatestEntries(1, 
entryCount.Value,out totalItems);
if (entryCount < totalItems)
return View(entries);
private void AddMoreUrlToViewData(intentryCount)
ViewData["moreUrl"] = Url.Action("Index", "Home",
 new { entryCount = entryCount + defaultEntryCount });

The method begins by making sure that the entryCount variable has a value, setting it to a default value if the parameter is null. It then retrieves as many of the latest blog entries as entryCount specifies by calling the GetLatestEntries method. I’ve omitted the GetLatestEntries method as it’s implementation will vary depending on blogging platform. The GetLatestEntries method also has an out parameter, totalItems, which tells us the total number of blog entries. I’m not a big fan of using out parameters but that’s the way the framework that I used for my blog (EPiServer Community) works so I decided to follow that pattern for consistency. If you use some other type of blogging platform I would recommend making a field of the totalItems.

The method moves on to check if there are more blog entries than the  number that will be displayed, in other words if a link for showing more entries should be displayed. If so, it calls the AddMoreUrlToViewData which, you guessed it, adds a route URL for displaying more entries to the ViewData dictionary.

Finally the method returns a ViewResult with the list of blog entries as the model.

Creating the views

The Index view for the Home controller is very simple. It simply renders a partial view named EntryTeaserList, passing along the list of blog entries (Model) and the it’s ViewData dictionary.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<IEnumerable<Entry>>" %>
<% Html.RenderPartial("EntryTeaserList", Model, ViewData); %>

The partial view EntryTeaserList offers a bit more excitement. It renders an ordered list and displays a teaser for each blog entry by rendering another partial view, EntryTeaser, inside a list item, passing in each individual blog entry as model to it. It also checks if the ViewData dictionary contains a URL for a more link. If it does it renders a link with that URL in the href attribute.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Entry>>" %>
<div id="entryTeaserList">
<% foreach (Entry item in Model) { %>
<li class="entryTeaser">
<% Html.RenderPartial("EntryTeaser", item); %>
<% } %>
<% if(ViewData["moreUrl"] != null) { %>
<a href='<%= ViewData["moreUrl"] %>' id="moreLink">More</a>
<% } %>

Finally I made the link look like a button with some CSS.

#moreLink {
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border: 1px solid #666666;
width: 100%;
display: block;
text-align: center;
padding: 0.4em 0 0.4em 0;
font-weight: bold;
#moreLink:hover {
background:url('/styles/gfx/more-bg.gif') 0 -64px; repeat-x;
border: 1px solid #888888;
text-decoration: none;

As you might have noticed I used CSS to round the buttons corners. This will only work for some browsers. In this particular case I though that that was OK, but in many other situations I would instead have used images or javascript. You might also have noticed that the button has the same background image when it’s hovered over as when it isn’t. The background image is however offset vertically so it appears that it’s actually another image. I did this to keep the number of HTTP requests required to load the page to a minimum.

Spicing things up with AJAX

With the controller and views set up as described above I was done with the non-AJAX functionality. This will work fine for visitors that doesn’t have javascript enabled or debugging purposes, but this kind of paging is pretty pointless if the page has to reload. After all the point is that when someone clicks the more button the experience shouldn’t be that another page is displayed but that the list, more or less instantly, just grows a bit.

To add the AJAX functionality I begun by modifying the controllers Index method.

public ActionResult Index(int? entryCount)
if (!entryCount.HasValue)
entryCount = defaultEntryCount;
int totalItems;
int page = entryCount.Value / defaultEntryCount;
//Retrieve the page specified by the page variable with a page size o defaultEntryCount
IEnumerable<Entry> pagedEntries = GetLatestEntries(page,
 defaultEntryCount, out totalItems);
if(entryCount < totalItems)
return View("EntryTeaserList", pagedEntries);
//Retrieve the first page with a page size of entryCount
IEnumerable<Entry> entries = GetLatestEntries(1, 
entryCount.Value, outtotalItems);
if (entryCount < totalItems)
return View(entries);

The added code checks if the current request is an AJAX request, with the IsAjaxRequest extension method that ships with MVC. IsAjaxRequest determines if the current request is an AJAX request by looking for and at the X-Requested-With request header. If such an header, or actually any request parameter with that name, is set to “XMLHttpRequest” the method will return true. As jQuery’s AJAX methods sets that header this method works great in this example.

Anyway, if the current request is an AJAX request we know that the visitors browser already displays a number of blog entry teasers and instead of returning the full number of entries specified by the entryCount parameter we should only return those that haven’t yet been sent to the visitors browser. So, we calculate what page (as if we where using traditional paging) is requested by dividing entryCount with the defaultEntryCount constant. Then we retrieve a list of the entries on that page with a page size of defaultEntryCount. That is we retrieve the defaultEntryCount number of entries with an offset of page*defaultEntryCount.

Finally, if there are more entries we set the moreUrl in the ViewData dictionary by calling the AddMoreUrlToViewData method and return a ViewResult. This time around however we don’t return the default view for the method. Instead we return the EntryTeaserList partial view. This way we don’t return more HTML than necessary but we are able to reuse an already existing view. We could of course have returned the result as JSON or XML instead but that would have forced us to write javascript for rendering the markup to display the result and thereby duplicating the same markup in two places.

The last thing I did was to add a few lines of javascript to intercept clicks on the more link.

$(function() {
function addMoreLinkBehaviour() {
$('#entryTeaserList #moreLink').live("click", function() {
$(this).html("<img src='/images/ajax-loader.gif' />");
$.get($(this).attr("href"),function(response) {
$('#entryTeaserList ol').append($("ol", response).html());
$('#entryTeaserList #moreLink').replaceWith($("#moreLink", response));
return false;

When the DOM is ready we add a function to the click event of the more link, and, since I’m using the live function, to any future objects matching that selector. When the link is clicked two things initially happen. First the link’s text is replaced with an image to give the visitor some visual feedback if the response of the AJAX request isn’t instantly returned. Then an AJAX request is made to the same URL as the link had in it’s href attribute. That is, there’s no special URL for the AJAX request. This works as the controller takes care of determining what type of request it is.

When the server has responded with the partial view, that is an ordered list and possibly a new more link the list items are appended to the existing ordered list and the more link is replaced with the new more link if it exists. This way the more link is automatically updated with a new URL in it’s href attribute and the loading image is replaced with the original text.


I personally find this solution pretty elegant. It requires quite few lines of code and almost no duplicate logic or markup at all. It also offers full fallback functionality for visitors without javascript. However, if I was really interested in offering the best possible experience to human visitors with javascript disabled I could also give each blog entry teaser an id with it’s number in the list and include a hash tag with entryCount + 1 – defaultEntryCount in the more link’s target URL so that they would automatically be scrolled to the first entry that was added to the list. In my case I deemed that to be overkill though.

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

S3Captcha For MVC

Windows 7 Enterprise x86 1 link !



Windows 7 Enterprise x86
File Name : en_windows_7_enterprise_x86_dv d_x15-70745.iso
File Size : 2.24 GB
Date Posted: 8/6/2009 9:56 AM ISO/CRC: 6A9B5097
SHA1: C6B905E48FDB6CB5BFCA967715A644 61B812D40C…_x15-70745.iso

Windows Se7en XP x86 – Black Edition (08-2010)


All driverpacks are included :
DriverPack Graphics A 8.12.1
DriverPack Graphics B 8.12.1 DriverPack Graphics C 8.12.1
DriverPack LAN 8.12.1
DriverPack Mass Storage 9.01
DriverPack Sound A 8.05
DriverPack Sound B 8.05
DriverPack WLAN 8.06
DriverPack CPU 8.04
CCleaner 2.21.940
dfxWMP [for more voice in WMP11]
DirectX 9.0c
Flash Player 10 IE/FF
IconPackager 3.2
Internet Explorer 8
Java[TM] 6 Update 15
Messenger Plus for WLM 9
Mozilla Firefox 3.5.0
NetFramework 2.0
Silverlight 2.0
Winrar 3.80
Ueber icon 1.0.4
Windows Media Player 11
Windows Live Messenger 9.0
Yahoo 10
– Cyber Se7en Black Edition theme
– Cpls
– Cursors
– Fonts
– Wallpapers


Name: XP Se7en Black Edition (700mb)
Service Pack: 3
System: x86 32bit
Product K.@.y: Not Needed
This version of Windows XP is designed for your convenience
Password : allmedia4u@soft

Biến Windows lậu thành Windows có bản quyền

Đầu tiên vào Start ,Run,gõ Regedit rùi tìm đến khóa

Ở ô bên phải nhấn chuột phải vào OOBETimer rồi click vào Modify. Tiếp đến hãy thay đổi một khóa bất kì (ví dụ 71 thành 72 chẳng hạn). Sau đó đóng nó lại và tiếp tục vào Start , Run , và đánh

%systemroot%\system32\oobe\msoobe.exe /a

Nó sẽ đưa bạn đến cửa sổ Active windows.

Đừng lo hãy chọn
I want to telephone a customer service representative to activate Windows

Tiếp đến nhấn Next, nhấn Change Product key
Hãy nhập key này


Đánh xong hãy nhấn Update. Nó sẽ lại đưa chúng ta về cửa sổ Active, đừng quan tâm, hãy đóng nó lại bằng cách nhấn vào Remind me later
Xong đâu đó rùi thì còn chờ gì nữa, khởi động lại Windows đi thôi. Khởi động lại xong hãy vào Run, đánh tiếp

%systemroot%\system32\oobe\msoobe.exe /a

Cửa sổ Active sẽ lại hiện ra nhưng ko phải là bắt chúng ta Active mà là báo cho ta biết Windows is activated.

Vậy là Windows đã có bản quyền rùi đó. Hãy tận hưởng bằng cách vào ngay trang update hay cài IE7, WMP11, Windows Defender …. hay bất cứ cái gị có check bản quyền của Microsoft.