• [翻译]ASP.NET MVC 3 开发的20个秘诀(十七)[20 Recipes for Programming MVC 3]:卷帘式分页加载


    议题

    现在很多网站都与数据库进行交互。如果网站流量很大,使用SQL来检索数据会带来非常大的压力。更重要的是,用户希望在点击链接之后15秒内得到响应的内容,而在页面加载的时,显示之外滚动条下面的内容可能多数内容都是不必要的(滚动条之外没显示的部分)。为了解决这个问题,采取内容“需求点播”方式加载。页面首先会加载足够的内容,当用户在阅读并向下滚动的时候,页面会在不影响用户阅读体验的情况下继续加载更多的内容。

     

    解决方案

    当用户开始滚动网站内容时,使用JQuery将前期加载的内容具体数值传回异步控制器,然后按需加载相关的内容。

     

    讨论

    异步控制器可能是MVC程序集中迄今为止被利用最少的或最不为人所知的控制器,当然也有可能是不知道怎么用它。以下内容是摘抄自MSDN网站的介绍信息:

     

    在可能出现线程不足的应用程序中,您可以配置通过异步方式处理操作。异步请求与同步请求所需的处理时间相同。例如,如果某个请求生成一个需要两秒钟来完成的网络调用,则该请求无论是同步执行还是异步执行都需要两秒钟。但是,在异步调用的过程中,服务器在等待第一个请求完成的过程中不会阻塞对其他请求的响应。因此,当有许多请求调用长时间运行的操作时,异步请求可以防止出现请求排队的情况。

     

    在这个示例中,使用异步请求将是个完美的解决方案,当新用户在发起更为重要的请求时,它将会自动释放IIS资源,因为其中用户的大多数“需求点播”是不太重要的,因为大多数人甚至不会注意到正在加载的额外的内容。

     

    在大多数社交网站中,用户的批注信息更多可能包含的是活动信息。在以前的秘诀中,实现了为书记添加评论的功能。在这个例子中,将会修改页面,列出最近的评论。当用户为了查看更多的评论,他们就会开始滚动,一旦用户开始滚动页面,就发起Ajax请求,请求异步控制器获取剩余部分评论。

     

    首先,修改Home/Index视图,使其显示最近的评论信息。提供书籍最近的相关评论并显示查看书籍基本资料的相关链接。创建新的控制器用来显示评论,这个视图将会调用render方法来显示剩下的信息。

    @model IEnumerable<MvcApplication4.Models.BookComment>
    @{
    ViewBag.Title = "Home Page";
    }
    <h2>@ViewBag.Message</h2>
    <p>
    To learn more about ASP.NET MVC visit
    <a href="http://asp.net/mvc"
    title
    ="ASP.NET MVC Website">
    http://asp.net/mvc </a>.
    </p>
    <script type="text/javascript">
    var lastY = 0;
    var currentY = 0;
    var page = 1;
    var maxPages = @ViewBag.maxPages;
    $(window).scroll(
    function () {
    if (page < maxPages) {
    currentY
    = $(window).scrollTop();
    if (currentY - lastY > 200 * (page - 1)) {
    lastY
    = currentY;
    page
    ++;
    $.get(
    'CommentFeed/Comments?page=' + page,
    function(data) {
    $(
    '#comments').append(data);
    });
    }
    }
    });
    </script>
    <div id="comments">
    <h2>Recent Comments</h2>
    @Html.Partial("../CommentFeed/Comments", Model)

    </div>

    在上面示例代码中,当浏览器窗体滚动,JavaScript代码就开始执行。在这段代码中定义了一些Javascript全局变量,保持追踪当前滚动条“Y”坐标的位置,最后“Y”坐标的位置和当前被检索到的页面位置。当窗口的ScrollTop减去“Y”坐标最后的位置大于某个具体数字,则通过Ajax请求书籍的其他评论信息。为确保新内容能及时被加载,必须要根据自己网站的内容高度,调整到最佳的像素值。

     

    接下来,需要修改HomeController添加检索书籍评论列表。为了确保最新的评论首先显示,排序使用创建日期降序的排列方法。为了减轻数据库的负载,每次只加载固定数量的评论而不是全部,但是也要保证,在滚动时显示足够的内容。在下面的示例当中,评论的加载数量将会限制为3条。页面的最大加载次数也被限制为评论总数除以3的结果。设置最大页数,以防止在加载完毕后,产生无效Ajax请求。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Globalization;
    using System.Data.Entity;
    using MvcApplication4.Models;
    namespace MvcApplication4.Controllers
    {
    public class HomeController : Controller
    {
    private BookDBContext db = new BookDBContext();
    public ActionResult Index()
    {
    ViewBag.Message = "Welcome to ASP.NET MVC!";

    // Get our recent comments
    var bookcomments = db.BookComments.Include(
    b => b.Book).OrderByDescending(b => b.Created).
    Take(3);
    var count = db.BookComments.Count();
    ViewBag.maxPages = count / 3 + 1;
    return View(bookcomments);
    }
    ...
    }
    }

     

    接下来,需要复制一个新的异步控制器。选中Controllers文件夹,右键单击选择“添加”→“控制器”,将新控制器命名为“CommentFeedController”。这个控制器不需要设置基架选项以及其他内容,直接点击“添加”即可。(译者注:然后将新创建的控制器类的父类改为“AsyncController

     

    这个控制器与之前的默认控制器看起来会有一些区别。异步控制器,每个视图都会有两个方法。第一个方法是用来实现异步请求(例如,获取评论信息)。第二个方法,是在异步调用时返回或显示接收到的结果。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MvcApplication4.Models;
    using System.Data.Entity;

    namespace MvcApplication4.Controllers
    {
    public class CommentFeedController : AsyncController
    {
    private BookDBContext db = new BookDBContext();
    public void CommentsAsync(int page)
    {
    AsyncManager.OutstandingOperations.Increment();

    AsyncManager.Sync(() =>
    {
    var bookcomments = db.BookComments.Include(
    b => b.Book).OrderByDescending(b =>
    b.Created).Skip(page * 3).Take(3);
    AsyncManager.Parameters["bookcomments"] =
    bookcomments;
    AsyncManager.OutstandingOperations.Decrement();
    });
    }

    public ActionResult CommentsCompleted(
    IEnumerable<BookComment> bookcomments)
    {
    return PartialView(bookcomments);
    }
    }
    }

    第一个方法,“CommentsAsync”,接收从Javascript传回的当前的页码,使用这个值来检索接下来的3条评论。首先是调用OutstandingOperations来通知未完成的请求挂起。然后再将检索评论的代码作为一个方法变量执行第二步操作,最后,再从未完成的计数器中将执行方法减去。在这里最重要的是递增和递减在计数器中的匹配,当递增和递减计数器相同的一段时间后,同步管理器将取消请求,否则,请求永远无法结束。

     

    第二个方法,接收书籍的评论信息,并返回一个分部视图结果。这是一个与Home/Index视图相同的分部视图。在这里最后一步就是创建这个分部视图。右键单击“Views”文件夹,选择“添加”→“新建文件夹”,并将文件夹命名为“CommentFeed”,然后右键单击此文件夹,选择“添加”→“视图”,将其命名为“Comments”,然后确保选中创建视图对话框中的“创建分部视图”选项,然后点击“添加”。

     

    @model IEnumerable<MvcApplication4.Models.BookComment>
    @foreach (var item in Model) {
    <h3><a href="@Url.Action("Details", "Books", new {
    ID
    =item.Book.ID } )">
    @Html.DisplayFor(modelItem => item.Book.Title)
    </a></h3>
    <h4>Comment Posted: @Html.DisplayFor(
    modelItem => item.Created)</h4>
    <p>@MvcHtmlString.Create(Html.Encode(item.Comment).Replace(
    Environment.NewLine, "<br />"))</p>

    }

     

    如上所示,首先将评论按照创建时间排序循环取出,显示书籍标题以及详情链接,评论的创建日期以及最后的评论文本。因为评论中有可能会包含换行符,将其中换行符替换为“<br />”标记。

     

     

    参考

    Asynchronous Controllers 原书地址 书籍源代码

  • 相关阅读:
    单选框和复选框(radiobox、checkbox)
    三种alertconfirmprompt弹窗的处理方法
    iframe的切换
    python的class(类)中的object是什么意思?
    loadrunner12自带的机票预订服务,解决httpd: Could not reliably determine the server's fully qualified domain name 问题
    使用错误的用户名和密码也能运行通过
    win10删除IE某些文件导致不可用恢复的方法
    win10系统删除需要Trustedlnstaller权限的文件
    loadrunner各版本对应的ie浏览器版本
    vue之vue-router加深印象
  • 原文地址:https://www.cnblogs.com/o2ds/p/2301660.html
Copyright © 2020-2023  润新知