【问题标题】:MVC3 - Asynchronous PaginationMVC3 - 异步分页
【发布时间】:2018-10-15 00:18:31
【问题描述】:

我有一个在我家中使用分页的对象列表> index.cshtml。当用户单击对象的每个页面时,我只想刷新页面的该部分,而不是其他任何内容。我将如何做到这一点?

理想情况下,我想使用异步方法和 ControllerActions...

控制器 > HomeController.cs

public ViewResult Index(int page = 1) {
ProductsListViewModel viewModel = new ProductsListViewModel {
Products = repository.Products
.OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize),
PagingInfo = new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = repository.Products.Count()
}
};
return View(viewModel);
}

首页 > 索引.cshtml:

@model SportsStore.WebUI.Models.ProductsListViewModel
@{
ViewBag.Title = "Products";
}
@foreach (var p in Model.Products) {
<div class="item">
<h3>@p.Name</h3>
@p.Description
<h4>@p.Price.ToString("c")</h4>
</div>
}
<div class="pager">
@Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new {page = x}))
</div>

HtmlHelper > PagingHelper.cs

namespace SportsStore.WebUI.HtmlHelpers {
public static class PagingHelpers {
public static MvcHtmlString PageLinks(this HtmlHelper html,
PagingInfo pagingInfo,
Func<int, string> pageUrl) {
StringBuilder result = new StringBuilder();
for (int i = 1; i <= pagingInfo.TotalPages; i++) {
TagBuilder tag = new TagBuilder("a"); // Construct an <a> tag
tag.MergeAttribute("href", pageUrl(i));
tag.InnerHtml = i.ToString();
if (i == pagingInfo.CurrentPage)
tag.AddCssClass("selected");
result.Append(tag.ToString());
}
return MvcHtmlString.Create(result.ToString());
}
}
}

【问题讨论】:

  • 你有没有在局部视图中放置网格

标签: asp.net-mvc-3 asynchronous pagination


【解决方案1】:

您可以使用 AJAX。第一步是将要刷新的内容放到一个partial中,放到自己的div中:

@model SportsStore.WebUI.Models.ProductsListViewModel
@{
    ViewBag.Title = "Products";
}

<div id="products">
    @Html.Partial("_products", Model.Products)
</div>

<div class="pager">
    @Html.PageLinks(Model.PagingInfo, x => Url.Action("Index", new { page = x }))
</div>

然后你当然会有对应的_Products.cshtml partial:

@model IEnumerable<SportsStore.WebUI.Models.ProductViewModel>
@foreach (var p in Model.Products) {
    <div class="item">
        <h3>@p.Name</h3>
        @p.Description
        <h4>@p.Price.ToString("c")</h4>
    </div>
}

然后调整您的控制器操作,使其能够响应 AJAX 请求:

public ActionResult Index(int page = 1) 
{
    var viewModel = new ProductsListViewModel 
    {
        Products = repository.Products
            .OrderBy(p => p.ProductID)
            .Skip((page - 1) * PageSize)
            .Take(PageSize),
        PagingInfo = new PagingInfo 
        {
            CurrentPage = page,
            ItemsPerPage = PageSize,
            TotalItems = repository.Products.Count()
        }
    };
    if (Request.IsAjaxRequest())
    {
        return PartialView("_Products", viewModel);
    }

    return View(viewModel);
}

现在剩下的就是对您的分页锚点进行 AJAX 化。可以在一个单独的 javascript 文件中完成,您可以在其中使用 jQuery 订阅它们的 .click() 事件并将默认操作替换为 AJAX 请求:

$(function() {
     $('.pager a').click(function() {
         $.ajax({
             url: this.href,
             type: 'GET',
             cache: false,
             success: function(products) {
                 $('#products').html(products);
             }
         });

         // prevent the default redirect
         return false;
     });
});

【讨论】:

  • 通过将Index 操作的返回类型从ViewResult 更改为ActionResult。我已经更新了我的答案。我没有注意到你已经修改了这个。您应该始终将 ActionResult 作为您的操作的返回类型,这是结果层次结构中的最高类。
  • 不,return PartialView("_Products", viewModel); 不应包含主布局。您确定 AJAX 请求有效并且您输入了if 条件吗?
  • 您收到 500 错误。您的控制器操作中是否引发异常?还是在渲染部分时?使用 FireBug 探索 AJAX 请求的响应并查看此错误的确切原因。您有 2 个寻呼机这一事实不应该改变或使任何事情复杂化。它应该可以工作。
  • 这是因为cache: false AJAX 参数添加了一个随机数以确保请求不被浏览器缓存。您可以使用 POST 而不是 GET,在这种情况下您不再需要 cache: false。但这不应该是您的问题的原因。
  • 链接已经使用页面查询字符串参数指向正确的控制器操作。 javascript 所做的就是对这个链接进行 AJAXify。因此,请确保您的链接指向正确的操作。
猜你喜欢
  • 2018-08-13
  • 2016-10-11
  • 2015-12-22
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 2018-03-14
相关资源
最近更新 更多