Chapter 20. Paging, Views, and Ajax

In this chapter, we focus on the user interface. In the first part of this chapter, we add support for paging through blog entries. Next, we create the views for our blog application. Finally, we modify our blog application to take advantage of Ajax.

We have only two user stories that we need to implement (see Figure 20.1). One story for paging and one story for Ajax.

Figure 20.1. The user stories

image

Adding Paging Support

Our first user story concerns paging. We don’t want users of the blog application to get overwhelmed with too many blog entries displayed in a page at one time. According to the user story:

No more than five blog entries should be displayed on a page at a time. When there are more than five entries, the user should navigate to earlier entries.

In Chapter 6, “Understanding HTML Helpers,” we implemented a simple paging framework. We can take advantage of that framework here in our blog application.

In the paging framework, we use the class in Listing 20.1 to represent a page of items.

Listing 20.1. UnleashedBlogPagingPageList.cs (C#)

image


Listing 20.1. UnleashedBlogPagingPageList.vb (VB)

image

image


The nice thing about the PagedList class in Listing 20.1 is that it represents not only a page of items, but it also represents additional properties such as the total page count and the page size.

We want to modify our blog application to use this paging framework. However, before we can start rewriting our application code, we first need to create some tests.

Here’s what we want to test:

  1. The Index() action should accept a page parameter.
  2. The Index() action exposed by the Blog controller should return an instance of the PagedList class that corresponds to the page parameter.
  3. The PagedList returned by the Blog Index() action should never contain more than five blog entries.
  4. The PageList returned by the Blog Index() action should order the blog entries by date (latest blog entry first).

This list gives us the four tests that are contained in Listing 20.2.

Listing 20.2. UnleashedBlog.TestsControllersBlogControllerTests.cs (C#)

image

image

Listing 20.2. UnleashedBlog.TestsControllersBlogControllerTests.vb (VB)

image

image


When we first attempt to run the tests in Listing 20.2, they fail. The tests won’t even build because the Blog controller Index() action does not currently accept a page parameter (see Figure 20.2).

Figure 20.2. New tests fail because of a missing page parameter.

image

Before we do anything else, we need to write just enough code so that our solution compiles. We need to modify the Blog controller Index() action so that it accepts a page parameter and returns a PagedList. The modified Index() action is contained in Listing 20.3.

Listing 20.3. UnleashedBlogBlogController.cs (C#)

image


Listing 20.3. UnleashedBlogBlogController.vb (VB)

image


Unfortunately, modifying the Index() action introduces new problems with our test code. Three tests that passed before now fail because we have modified our Index() action (see Figure 20.3).

Figure 20.3. Old tests fail because of a new page parameter.

image

This problem is easy enough to fix. We just need to update the old tests so that the tests pass a NULL value when calling the Index() action. After we make this change to the test code, the first of our four new tests pass.

To get the next test to pass, we need to modify our application code so that the Index() action returns a PagedList. However, it cannot be just any PagedList. The PagedList must represent the set of blog entries that correspond to the page passed to the Index() action.

The modified Index() action in Listing 20.4 passes the page parameter to the ListBlogEntries() method.

Listing 20.4. UnleashedBlogControllersBlogController.cs (C#)

image


Listing 20.4. UnleashedBlogControllersBlogController.vb (VB)

image


We need to modify the ListBlogEntries() method so that it accepts a page parameter (see Listing 20.5).

Listing 20.5. UnleashedBlogModelsBlogService.cs (C#)

image


Listing 20.5. UnleashedBlogModelsBlogService.vb (VB)

image


Finally, we need to modify the Blog repository so that it returns the records that correspond to a particular page. The updated Blog repository ListBlogEntries() method is contained in Listing 20.6.

Listing 20.6. UnleashedBlogModelsBlogRepositoryBase.cs (C#)

image


Listing 20.6. UnleashedBlogModelsBlogRepositoryBase.vb (VB)

image


In Listing 20.6, the ListBlogEntries() method has been modified to return a PagedList class. Notice the final statement. The final statement calls the ToPagedList() extension method (defined in the PagingLinqExtensions class) to return a PagedList from a query.

After we make all these changes, all our tests pass except for one (see Figure 20.4). Unfortunately, our blog entries are not returned in the right order. We want to display the blog entry with the latest publication date first.

Figure 20.4. Blog entries are returned in the wrong order.

image

We need to make one last change to our Blog repository ListBlogEntries() method. We need to order the blog entries by the date published. We can do this by calling the OrderByDescending() LINQ method on our query (see Listing 20.7). Finally, all the tests pass (see Figure 20.5).

Figure 20.5. All tests pass!

image

Listing 20.7. UnleashedBlogModelsBlogRepositoryBase.cs (C#)

image


Listing 20.7. UnleashedBlogModelsBlogRepositoryBase.vb (VB)

image


Adding the Views

It is finally time to improve the appearance of our blog application. In this section, we create the views and partials for our blog.

Let’s start with the default page—the page generated by the view returned by the Blog controller Index() action. This view displays the list of blog entries (see Figure 20.6).

Figure 20.6. The Blog Index view

image

Because we changed the view data model returned by the Blog controller Index() action, we need to delete the existing Index view and re-create it with the correct view data model class. Replace the existing Index view with the Index view in Listing 20.8.

Listing 20.8. UnleashedBlogViewsBlogIndex.aspx (C#)

image


Listing 20.8. UnleashedBlogViewsBlogIndex.aspx (VB)

image


Notice that the view in Listing 20.8 has an Inherits attribute that causes the view data model to be cast to a PagedList<BlogEntry> class.

The Index view delegates all its blog entry rendering work to a partial named BlogEntries. The BlogEntries partial renders all the blog entries and the pager user interface.

The BlogEntries partial is used by both the Blog Index view and the Archive Index view. By creating a separate partial, we’ve eliminated duplicate user interface content among the views in our application.

The BlogEntries partial is contained in Listing 20.9.

Listing 20.9. UnleashedBlogViewsSharedBlogEntries.ascx

image


Listing 20.9. UnleashedBlogViewsSharedBlogEntries.ascx (VB)

image


Notice that the BlogEntries partial uses two custom HTML helpers. First, the Html.BlogLink() helper renders a link to a blog entry. This helper is contained in Listing 20.10.

Listing 20.10. UnleashedBlogHelpersBlogLinkHelper.cs

image


Listing 20.10. UnleashedBlogHelpersBlogLinkHelper.vb (VB)

image


Note

To avoid registering the namespace for the HTML helpers in every page in which I use the helpers, I registered the namespace in the web.config file like this:

image

A second HTML helper renders the pager user interface (see Listing 20.11). This helper renders an Older Entries link when there are older entries and a Newer Entries link when there are newer entries. If there isn’t more than a single page of blog entries, the helper renders nothing at all.

Listing 20.11. UnleashedBlogHelpersBlogPagerHelper.cs (C#)

image

image


Listing 20.11. UnleashedBlogHelpersBlogPagerHelper.vb (VB)

image

image


Adding Ajax Support

I love my iPhone. The iPhone was designed to provide a great user experience. The iPhone has a number of user interface design innovations. One innovation concerns how paging is implemented.

Earlier in this chapter, we implemented a standard user interface for paging. We created Older Entries and Newer Entries links. When you first request the page, the first five blog entries display. When you click the Older Entries link, the first blog entries are replaced with the next blog entries.

In this section, we change our user interface for paging to take advantage of Ajax. Instead of displaying Older Entries and Newer Entries links, we only display a More Entries link. When you click the More Entries link, additional blog entries are appended to the first five blog entries. The list of blog entries grows instead of being replaced (see Figure 20.7).

Figure 20.7. Growing list of blog entries

image

Note

Even after we implement Ajax paging, our blog application continues to work with JavaScript disabled. When JavaScript is disabled, the blog application does a normal post to the server to retrieve the next set of five blog entries.

In this section, we improve the user experience and responsiveness of our blog application by adding support for Ajax. We focus on implementing the following user story:

When there are more than five entries, a More Entries link displays. When you click the More Entries link, five more blog entries are appended to the list of blog entries (see Figure 20.8).

Figure 20.8. Appending the additional blog entries

image

As always, we start with a test. There are now two ways that we want to retrieve blog entries: with a normal page request and with an Ajax request. In the first case, we want to return a ViewResult, and in the second case we want to return a PartialViewResult. The test in Listing 20.12 verifies that we can invoke an action that returns a PartialViewResult.

Listing 20.12. UnleashedBlog.TestsControllerTestsBlogControllerTests.cs (C#)

image


Listing 20.12. UnleashedBlog.TestsControllerTestsBlogControllerTests.vb (VB)

image


When we first attempt to run the test in Listing 20.12, it fails because the Blog controller does not have an Index_Ajax() action. Because we have a test, we can allow ourselves to add this new action (see Listing 20.13).

Listing 20.13. UnleashedBlogControllersBlogController.cs (C#)

image


Listing 20.13. UnleashedBlogControllersBlogController.vb (VB)

image


The Index_Ajax() action in Listing 20.13 is exactly the same as the Index() action, except the Index_Ajax() action returns a PartialViewResult instead of a normal ViewResult.

Notice that the Index_Ajax() action is decorated with two attributes. The AcceptAjax attribute causes this action to be called only in the context of an Ajax request. This attribute is not a standard part of the ASP.NET MVC framework. We discussed this attribute in Chapter 14, “Working with Ajax.”

The second attribute, the ActionName attribute, exposes the method as an action with a different name than the method name. This attribute causes the Index_Ajax() method to be exposed as the Index() action.

To take advantage of the new Index_Ajax() action, we need to modify our views. Listing 20.14 contains the updated Blog controller Index view.

Listing 20.14. UnleashedBlogViewsBlogIndex.aspx (C#)

image


Listing 20.14. UnleashedBlogViewsBlogIndex.aspx (VB)

image

Notice that the view in Listing 20.14 includes a loadingMoreEntries DIV element. The contents of this DIV element display while the blog application waits for the results of an Ajax request.

Note

I downloaded the busy wait image from www.ajaxload.info. This website enables you to generate different types of busy wait images and use them in your applications for free.

The updated BlogEntries partial is contained in Listing 20.15.

Listing 20.15. UnleashedBlogViewsSharedBlogEntries.ascx (C#)

image


Listing 20.15. UnleashedBlogViewsSharedBlogEntries.ascx (VB)

image


Only one change has been made to the partial in Listing 20.15. The BlogEntries partial now uses an Ajax.BlogPager() instead of the Html.BlogPager().

The Ajax.BlogPager() is contained in Listing 20.16.

Listing 20.16. UnleashedBlogHelpersBlogPagerHelper.ascx (C#)

image


Listing 20.16. UnleashedBlogHelpersBlogPagerHelper.ascx (VB)

image


The Ajax.BlogPager() calls the Ajax.ActionLink() helper method internally to render the More Entries link. An instance of the AjaxOptions class is created to specify the behavior of the Ajax.ActionLink(). The AjaxOptions class causes the link to update the blogEntries DIV tag with the results of the Ajax request.

After we make these changes, our blog application now supports Ajax. When we page through the blog entries by clicking the More Entries link, additional blog entries are appended to the existing page.

Summary

In this chapter, we focused on improving the user interface of our blog application. In the first part of this chapter, we added support for paging through blog entries. We took advantage of the paging framework that we created in Chapter 6.

Next, we rewrote the views and partials for our blog application. Our views share a single partial that displays the list of blog entries. That way, we can control the appearance of our blog entries by modifying a single file.

Finally, we added Ajax support to our blog application. We created an Ajax pager that enables us to continuously grow our page by appending new blog entries to the existing blog entries.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.28.70