ASP.NET MVC:从视图调用控制器方法

5

我正在为ASP.NET MVC视图实现分页,我想从视图中调用控制器中的方法。

视图中的代码:

<a href="<%= Url.Action("Search", 
            new { page = NextPage(Request["exactPage"])).ToString()}) %>"> 

控制器方法:

public string NextPage(string currentPage)
{
     return (int.Parse(currentPage) +  1).ToString();
}

我该如何从视图中调用NextPage方法?

谢谢!


@爱丽丝梦游仙境:您可以通过将文本缩进4个空格(选择并按Ctrl+K)来将其格式化为代码。这将允许您使用特殊字符,如<,而不会出现问题。 - Peter Lang
3个回答

2

我忘记了它来自哪里。也许有人可以在评论中发布链接。

我认为这是代码完成的状态。

我将其作为一个项目;

MvcPaging;

IPagedList

using System.Collections.Generic;

namespace MvcPaging
{
    public interface IPagedList<T> : IList<T>
    {
        int PageCount { get; }
        int TotalItemCount { get; }
        int PageIndex { get; }
        int PageNumber { get; }
        int PageSize { get; }
        bool HasPreviousPage { get; }
        bool HasNextPage { get; }
        bool IsFirstPage { get; }
        bool IsLastPage { get; }
    }
}

PagedList

using System;
using System.Collections.Generic;
using System.Linq;
using MvcPaging;

namespace MvcPaging
{
    public class PagedList<T> : List<T>, IPagedList<T>
    {
        public PagedList(IEnumerable<T> source, int index, int pageSize)
            : this(source, index, pageSize, null)
        {
        }

        public PagedList(IEnumerable<T> source, int index, int pageSize, int? totalCount)
        {
            Initialize(source.AsQueryable(), index, pageSize, totalCount);
        }

        public PagedList(IQueryable<T> source, int index, int pageSize)
            : this(source, index, pageSize, null)
        {
        }

        public PagedList(IQueryable<T> source, int index, int pageSize, int? totalCount)
        {
            Initialize(source, index, pageSize, totalCount);
        }

        #region IPagedList Members

        public int PageCount { get; private set; }
        public int TotalItemCount { get; private set; }
        public int PageIndex { get; private set; }
        public int PageNumber { get { return PageIndex + 1; } }
        public int PageSize { get; private set; }
        public bool HasPreviousPage { get; private set; }
        public bool HasNextPage { get; private set; }
        public bool IsFirstPage { get; private set; }
        public bool IsLastPage { get; private set; }

        #endregion

        protected void Initialize(IQueryable<T> source, int index, int pageSize, int? totalCount)
        {
            //### argument checking
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException("PageIndex cannot be below 0.");
            }
            if (pageSize < 1)
            {
                throw new ArgumentOutOfRangeException("PageSize cannot be less than 1.");
            }

            //### set source to blank list if source is null to prevent exceptions
            if (source == null)
            {
                source = new List<T>().AsQueryable();
            }

            //### set properties
            if (!totalCount.HasValue)
            {
                TotalItemCount = source.Count();
            }
            PageSize = pageSize;
            PageIndex = index;
            if (TotalItemCount > 0)
            {
                PageCount = (int)Math.Ceiling(TotalItemCount / (double)PageSize);
            }
            else
            {
                PageCount = 0;
            }
            HasPreviousPage = (PageIndex > 0);
            HasNextPage = (PageIndex < (PageCount - 1));
            IsFirstPage = (PageIndex <= 0);
            IsLastPage = (PageIndex >= (PageCount - 1));

            //### add items to internal list
            if (TotalItemCount > 0)
            {
                AddRange(source.Skip((index) * pageSize).Take(pageSize).ToList());
            }
        }
    }
}

分页器

using System;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcPaging
{
    public class Pager
    {
        private ViewContext viewContext;
        private readonly int pageSize;
        private readonly int currentPage;
        private readonly int totalItemCount;
        private readonly RouteValueDictionary linkWithoutPageValuesDictionary;

        public Pager(ViewContext viewContext, int pageSize, int currentPage, int totalItemCount, RouteValueDictionary valuesDictionary)
        {
            this.viewContext = viewContext;
            this.pageSize = pageSize;
            this.currentPage = currentPage;
            this.totalItemCount = totalItemCount;
            this.linkWithoutPageValuesDictionary = valuesDictionary;
        }

        public string RenderHtml()
        {
            int pageCount = (int)Math.Ceiling(this.totalItemCount / (double)this.pageSize);
            int nrOfPagesToDisplay = 10;

            var sb = new StringBuilder();

            // Previous
            if (this.currentPage > 1)
            {
                sb.Append(GeneratePageLink("Previous", this.currentPage - 1));
            }
            else
            {
                sb.Append("<span class=\"disabled\">Previous</span>");
            }

            int start = 1;
            int end = pageCount;

            if (pageCount > nrOfPagesToDisplay)
            {
                int middle = (int)Math.Ceiling(nrOfPagesToDisplay / 2d) - 1;
                int below = (this.currentPage - middle);
                int above = (this.currentPage + middle);

                if (below < 4)
                {
                    above = nrOfPagesToDisplay;
                    below = 1;
                }
                else if (above > (pageCount - 4))
                {
                    above = pageCount;
                    below = (pageCount - nrOfPagesToDisplay);
                }

                start = below;
                end = above;
            }

            if (start > 3)
            {
                sb.Append(GeneratePageLink("1", 1));
                sb.Append(GeneratePageLink("2", 2));
                sb.Append("...");
            }
            for (int i = start; i <= end; i++)
            {
                if (i == this.currentPage)
                {
                    sb.AppendFormat("<span class=\"current\">{0}</span>", i);
                }
                else
                {
                    sb.Append(GeneratePageLink(i.ToString(), i));
                }
            }
            if (end < (pageCount - 3))
            {
                sb.Append("...");
                sb.Append(GeneratePageLink((pageCount - 1).ToString(), pageCount - 1));
                sb.Append(GeneratePageLink(pageCount.ToString(), pageCount));
            }

            // Next
            if (this.currentPage < pageCount)
            {
                sb.Append(GeneratePageLink("Next", (this.currentPage + 1)));
            }
            else
            {
                sb.Append("<span class=\"disabled\">Next</span>");
            }
            return sb.ToString();
        }

        private string GeneratePageLink(string linkText, int pageNumber)
        {
            var pageLinkValueDictionary = new RouteValueDictionary(this.linkWithoutPageValuesDictionary);
            pageLinkValueDictionary.Add("page", pageNumber);
            //var virtualPathData = this.viewContext.RouteData.Route.GetVirtualPath(this.viewContext, pageLinkValueDictionary);
            var virtualPathData = RouteTable.Routes.GetVirtualPath(this.viewContext.RequestContext, pageLinkValueDictionary);

            if (virtualPathData != null)
            {
                string linkFormat = "<a href=\"{0}\">{1}</a>";
                return String.Format(linkFormat, virtualPathData.VirtualPath, linkText);
            }
            else
            {
                return null;
            }
        }
    }
}

PagingExtensions

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using MvcPaging;

namespace MvcPaging
{
    public static class PagingExtensions
    {
        public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount)
        {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, null, null);
        }

        public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, string actionName)
        {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, actionName, null);
        }

        public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, object values)
        {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, null, new RouteValueDictionary(values));
        }

        public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, string actionName, object values)
        {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, actionName, new RouteValueDictionary(values));
        }

        public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, RouteValueDictionary valuesDictionary)
        {
            return Pager(htmlHelper, pageSize, currentPage, totalItemCount, null, valuesDictionary);
        }

        public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, string actionName, RouteValueDictionary valuesDictionary)
        {
            if (valuesDictionary == null)
            {
                valuesDictionary = new RouteValueDictionary();
            }
            if (actionName != null)
            {
                if (valuesDictionary.ContainsKey("action"))
                {
                    throw new ArgumentException("The valuesDictionary already contains an action.", "actionName");
                }
                valuesDictionary.Add("action", actionName);
            }
            var pager = new Pager(htmlHelper.ViewContext, pageSize, currentPage, totalItemCount, valuesDictionary);
            return pager.RenderHtml();
        }

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize)
        {
            return new PagedList<T>(source, pageIndex, pageSize);
        }

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, int totalCount)
        {
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int pageIndex, int pageSize)
        {
            return new PagedList<T>(source, pageIndex, pageSize);
        }

        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int pageIndex, int pageSize, int totalCount)
        {
            return new PagedList<T>(source, pageIndex, pageSize, totalCount);
        }
    }
}

然后在我的控制器中;

public class IndexArticlesFormViewModel
{
    public IPagedList<Article> articles {get; set;}
    public IQueryable<string> userTags { get; set; }
    public string tag {get; set;}
}


    public ActionResult SearchResults(int? page, string tag)
    {
        IndexArticlesFormViewModel fvm = new IndexArticlesFormViewModel();
        fvm.articles = ar.Search(tag).ToPagedList(page.HasValue ? page.Value - 1 : 0, 8);
        fvm.tag = tag;

        return View(fvm);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SearchResults(int? page, string tag, FormCollection collection)
    {
        if (!string.IsNullOrEmpty(collection["txtSearch"]))
            return RedirectToAction("SearchResults", new {page = 1, tag = collection["txtSearch"] });

        return RedirectToAction("SearchResults", new { page = page, searchTerm = tag });
    }

然后是View视图;
<div class="pager">
    <%= Html.Pager(ViewData.Model.articles.PageSize, ViewData.Model.articles.PageNumber, ViewData.Model.articles.TotalItemCount, new { tag = Model.tag })%>
</div>

谢谢@Jason。我实际上找到了几个关于这段代码的参考,但是老实说我不记得它来自哪里了。不过它运行得很好。 - griegs

2
如果您知道当前页面的编号,那么您可以渲染链接,其中“page”值=当前页面加/减1,用于上一页和下一页的链接。您不需要视图询问控制器下一个/上一个页面号是什么。基于当前页面索引的值,视图可以推导出这些信息。
编辑:我建议控制器向视图传递另一个值,指示可用的总页面数。然后,视图可以将此值与当前页面编号进行比较,以确定是否显示“下一页”链接。

是的,但是如果最后一页是3,下一页将继续增加到100或其他数字。因此,当它到达最后一页时,我希望它保持在原地...这是我更愿意放入一个方法中的逻辑。 - Alice in wonderland
像这样的东西:<%(if (Request["exactPage"] < TotalPage)) {%> <a href="<%=Url.Action("Search", new { exactPage = int.Parse(Request["exactPage"]) + 1).ToString}) %>"> <%}%>(抱歉,我无法弄清如何格式化代码)对于网页来说有点冗长... - Alice in wonderland
1
@爱丽丝梦游仙境:你可以将这个逻辑封装在一个HTML帮助方法中,以使你的视图代码更易读。类似这样:Html.RenderNextPageLink(currentPage, totalPages) - pmarflee

0

正如其他人所建议的那样,HtmlHelper可能是适当的选择,但如果您确实想在某个其他类上调用静态方法,只需在视图顶部添加命名空间导入即可。

<%@ Import Namespace="YOURCONTROLLERNAMESPACE"%>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接