Click here to Skip to main content
Click here to Skip to main content

ASP.NET MVC Ajax Infinite Scroll

, 3 Nov 2013
Rate this:
Please Sign up or sign in to vote.
This is a simple infinite scroll with Ajax post and JSON. Have fun :)

Introduction

Infinite Scroll is a web design technique that prevents the browser scroll bar from scrolling to the bottom of the page, causing the page to grow with additional content instead.

Here, I have implemented Infinite Scroll with ASP.NET MVC, Ajax post and JSON result. With rendering Partial View to string, it makes it easy to use Ajax post and JSON result to display any complex view.

Using the Code

You can also find the code on Codeplex.

Getting Data

In this sample for data, we use some XML file with book items.

Here is some part of the XML file:

<book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, an evil sorceress, 
      and he own childhood to become queen of the world.</description>
   </book>   

We use Linq to XML to load data to our Book class, which is:

    public class Book
    {
        public string ID { get; set; }
        public string Author { get; set; }
        public string Title { get; set; }
        public string Genre { get; set; }
        public string Price { get; set; }
        public string PublishDate { get; set; }
        public string Description { get; set; }
    } 

For example, at first the user can see 5 books on the page, and when she/he scrolls down, the next 5 books will load and so on.

Number 5 is BlockSize, and BlockNumber is 1 at first, and growing by 1 every time, we scroll down and next block loads. So GetBooks function gives the BlockNumber 'th block with BlockSize books in it.

    public static class DataManager
    {
        /// <summary>
        /// Returns one block of book items
        /// </summary>
        /// <param name="BlockNumber">Starting from 1</param>
        /// <param name="BlockSize">Items count in a block</param>
        /// <returns></returns>
        public static List<Book> GetBooks(int BlockNumber, int BlockSize)
        {
            int startIndex = (BlockNumber - 1) * BlockSize;

            var filePath = AppDomain.CurrentDomain.BaseDirectory + "testData.xml";
            var doc = XDocument.Load(filePath);

            var books = (from p in doc.Descendants("book")
                        select new Book
                        {
                            ID = p.Attributes("id").Single().Value,
                            Author = p.Element("author").Value,
                            Title = p.Element("title").Value,
                            Genre = p.Element("genre").Value,
                            Price = p.Element("price").Value,
                            PublishDate = p.Element("publish_date").Value,
                            Description = p.Element("description").Value,
                        }).Skip(startIndex).Take(BlockSize).ToList();

            return books;
        }
    }  

This part is very similar to paging task.

Controllers and Views

To show one block of books, we have an Action with PartialView BookList:

        [ChildActionOnly]
        public ActionResult BookList(List<Book> Model)
        {
            return PartialView(Model);
        }   
@model List<mvcajaxinfinitescroll.Models.Book>
@foreach (var item in Model)
{
    <div style="height: 300px; background-color: #F3F3F3; margin-bottom: 30px;">
        <div style="padding: 30px; 
        font-size: 25px; color: #7b4f9d">@item.Title</div>
        <div style="padding-left: 30px; 
        font-size: 18px;">Author: @item.Author</div>
        <div style="padding-left: 30px; 
        font-size: 18px;">Genre: @item.Genre</div>
        <div style="padding-left: 30px; 
        font-size: 18px;">Price: @item.Price $</div>
        <div style="padding-left: 30px; 
        font-size: 18px;">Publish Date: @item.PublishDate</div>
        <div style="padding-left: 30px; padding-right: 30px; font-size: 18px;">
        Description: @item.Description</div>
    </div>
}   

On Index Action, we just get the first Block:

        public ActionResult Index()
        {
            int BlockSize = 5;
            var books = DataManager.GetBooks(1, BlockSize);
            return View(books);
        }  

and show it on view:

<div id="bookListDiv">
    @{Html.RenderAction("BookList", "Home", new { Model = Model });}
</div>  

We have InfinateScroll Post Action. It runs every time we scroll page down and need to populate the next block of data.

        [HttpPost]
        public ActionResult InfinateScroll(int BlockNumber)
        {
            //////////////// THis line of code only for demo. Needs to be removed ////
            System.Threading.Thread.Sleep(3000);
            //////////////////////////////////////////////////////////////////////////
            int BlockSize = 5;
            var books = DataManager.GetBooks(BlockNumber, BlockSize);
            JsonModel jsonModel = new JsonModel();
            jsonModel.NoMoreData = books.Count < BlockSize;
            jsonModel.HTMLString = RenderPartialViewToString("BookList", books);
            return Json(jsonModel);
        } 

This Action returns a Json. We wrote JsonModel class to return here as JsonResult:

public class JsonModel
    {
        public string HTMLString { get; set; }
        public bool NoMoreData { get; set; }
    } 

NoMoreData indicates that this is the last set of data and BlockNumber is the last number.

HTMLString is the HtmlString of BookList view. In this way, it is easy to return JSON and show next block using a little jquery. To get HtmlString, we have function RenderPartialViewToString.

protected string RenderPartialViewToString(string viewName, object model)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.RouteData.GetRequiredString("action");

            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = 
                ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                ViewContext viewContext = new ViewContext
                (ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();
            }
        }

And now let's see JavaScript we use to do Ajax post. On Index view, we have:

 <script type="text/javascript">
    var BlockNumber = 2;  //Infinate Scroll starts from second block
    var NoMoreData = false;
    var inProgress = false;

    $(window).scroll(function () {
        if ($(window).scrollTop() == $(document).height() - 
        $(window).height() && !NoMoreData && !inProgress) {

            inProgress = true;
            $("#loadingDiv").show();
            
            $.post("@Url.Action("InfinateScroll", 
            "Home")", { "BlockNumber": BlockNumber },
                    function (data) {
                        
                        BlockNumber = BlockNumber + 1;
                        NoMoreData = data.NoMoreData;
                        $("#bookListDiv").append(data.HTMLString);
                        $("#loadingDiv").hide();
                        inProgress = false;
                    });
        }
    });
</script> 
<div id="loadingDiv" 
style="text-align: center; display: none; margin-bottom: 20px;">
    <img alt="Loading" 
    src="@Url.Content("~/Content/Images/ajax-loader.gif")" />
</div>  

Please, let me know if you liked it Smile | :) ...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hovhannes Bantikyan
Software Developer Seven Smarts
Armenia Armenia
.Net developer

Comments and Discussions

 
QuestionGREAT!! Pinmemberhayk.nersisyan22-Jul-14 4:28 
QuestionHow to work with Automatic Image Montage with jquery. PinmemberCuongPuyol22-Jun-14 17:00 
GeneralAwesome thank you! Pinmemberwmuntslag5-Jun-14 14:09 
QuestionThank You PinmemberPlamen 태권도 Yovchev20-Dec-13 20:58 
QuestionCSS after update PinmemberMember 1047353117-Dec-13 19:19 
AnswerRe: CSS after update PinmemberMember 1047353117-Dec-13 20:56 
Questionneed help... PinprofessionalKumar Kovuru3-Dec-13 2:57 
AnswerRe: need help... PinmemberHovhannes Bantikyan6-Dec-13 8:58 
GeneralRe: need help... PinmemberKumar Kovuru6-Dec-13 18:57 
QuestionAjax Helper PinmemberIbrahim Islam19-Nov-13 21:04 
AnswerRe: Ajax Helper PinmemberHovhannes Bantikyan21-Nov-13 9:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 3 Nov 2013
Article Copyright 2013 by Hovhannes Bantikyan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid