ASP.Net MVC 5 Load list data via ajax

2019-05-12 01:09发布

问题:

I have a list in asp.net mvc 5

I have limited the number of records to be displayed in page.

now on scroll I do ajax call, the first call works fine but when I scroll down more it recall the function repeatedly 5 to 10 times and lost it again display the data, it was really strange, I could not find solution

My Controller:

public ActionResult Index()
{
    int starting = 0;
    if (Request.Form["starting"] != null)
    {
        starting = Convert.ToInt32(Request.Form["starting"]);
    }

    int takes = 15;
    if (Request.Form["takes"] != null)
    {
        takes = Convert.ToInt32(Request.Form["takes"]);
    }
    //string strpost = "&ajax=1";

    var query = db.MyEmployee.ToList().Skip(starting).Take(takes);


    if (Request.IsAjaxRequest())
    {

        starting = starting+15;
        query = db.MyEmployee.ToList().Skip(starting).Take(takes);
        ViewData["starting"] = starting;
        ViewBag.takes = takes;
        return PartialView("_PartialIndex",query);
    }
    ViewBag.starting = starting;
    ViewBag.takes = takes;
    return View(query);

}

My Model:

     public class Employee
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public string Email { get; set; }
}

My View and partial view code:

 <div id="mypage">
@model IEnumerable<MVC5WAuth.Models.Employee>

@{
    ViewBag.Title = "Index";
}

<h2>Index 1</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Id)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FullName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Email)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FullName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Email)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.Id })
            </td>
        </tr>
    }

</table>


<script type="text/javascript">


    $(window).scroll(function () {
        if ($(window).scrollTop() == $(document).height() - $(window).height()) {
            // ajax call get data from server and append to the div



            var ajax_image = "<img src='../Content/loading.GIF' >";
            $('#mypage').html(ajax_image);
            var params = '&starting=' + @ViewBag.starting + '&takes=' + @ViewBag.takes;
            $.ajax({
                url:'@Url.Action("Index", "Employees")',
                type: "POST",
                data: params,

            })
            .done(function (r) {

                $('#mypage').html(r);
            });

        }
    });

</script>

回答1:

You current code is just replacing the existing view each time you scroll and make a ajax call, not updating the existing view with the next set of rows you want. You code also has some inefficiencies such as materializing all your records to an in-memory set before calling .Skip() and .Take().

You need to break this into 2 separate methods and views, one to generate the initial view, and one to return a partial of just the records you want to append to the main view.

Controller

public ActionResult Index()
{
    return View();
}
public ActionResult Fetch(int startIndex)
{
    query = db.MyEmployee.OrderBy(x => x.ID).Skip(startIndex).Take(15);
    return PartialView(query);
}

Index.cshtml

@model IEnumerable<MVC5WAuth.Models.Employee>
....
<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.Id)</th>
            ....
        </tr>
    </thead>
    <tbody id="tbody">
        @{ Html.RenderAction("Fetch", new { startIndex = 0 }); } // generate the 1st 15 rows
    </tbody>
</table>

<script type="text/javascript">
    var start = 15;
    var url = '@Url.Action("Fetch")';
    var tbody = $('#tbody');
    $(window).scroll(function () {
        if ($(window).scrollTop() == $(document).height() - $(window).height()) {
            ....
            $.get(url, { startIndex: start }, function(response) {
                tbody.append(response);
                start += 15; // increment for next call
            });
        }
    });
</script>

Fetch.cshtml

@model IEnumerable<MVC5WAuth.Models.Employee>
@foreach (var item in Model)
{
    <tr>
        <td>@Html.DisplayFor(m => item.Id)</td>
        ....
    </tr>
}