在HtmlHelper方法中生成正确的URL

时间:2011-12-20 17:56:54

标签: asp.net-mvc-3 pagination html-helper

我已经构建了一个粗略的HTML Helper方法,目的是创建两个分页链接(下一个和上一个)。

以下是传递给Helper方法的ViewModel(DTO)的代码:

public class PaginationVM
{
    public int TotalItems { get; set; }
    public int ItemsPerPage { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages
    {
        get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); }
    }
}

以下是HTML Helper方法的代码:

public static MvcHtmlString Paginator(this HtmlHelper htmlHelper, PaginationVM pInfo)
{
    StringBuilder result = new StringBuilder();

    var nextPage = pInfo.CurrentPage + 1;
    var prevPage = pInfo.CurrentPage - 1;

    if (pInfo.CurrentPage < pInfo.TotalPages)
    {
        TagBuilder tagA = new TagBuilder("a");
        tagA.MergeAttribute("href", "page/" + nextPage);
        tagA.InnerHtml = "Prev";
        tagA.AddCssClass("prev");
        result.Append(tagA.ToString());
    }
    else
    {
        TagBuilder tagB = new TagBuilder("a");
        tagB.MergeAttribute("href", "page/" + prevPage);
        tagB.InnerHtml = "Next";
        tagB.AddCssClass("next");
        result.Append(tagB.ToString());
    }

    return MvcHtmlString.Create(result.ToString());
}

上面的代码组合似乎有效,但只有从主页,如果我点击Prev链接[localhost:xxxx / page / 2],然后转到第2页,则链接变为[localhost:xxxx / page / page / 2]。

我的路由如下

routes.MapRoute(
    "PagingPosts/param", // Route name
    "page/{pageId}", // /page/3
    new { controller = "Home", action = "Index", pageId = UrlParameter.Optional }, // Parameter defaults
    new { pageId = @"\d+" } // Constraints: pageId must be numerical
);

正如您所见,单词页面现在已重复。我可以想办法解决这个问题,那就是告诉它从root生成一个ActionLink,并以这种方式构建我的URL,但我不知道如何在HTML帮助器中做到这一点,以及最好的办法是。

非常感谢任何帮助

谢谢。

1 个答案:

答案 0 :(得分:4)

一个好方法是定义一个帮助器,它接受一个Func<int, string>委托,可以传递页码并返回生成的URL字符串。这样,paginator helper不会绑定到任何特定的路由,并且可以轻松地在您的应用程序中重复使用。

这样的东西
public static MvcHtmlString Paginator(this HtmlHelper htmlHelper, 
                                      PaginationVM pInfo, 
                                      Func<int, string> pageUrl)
{
    StringBuilder result = new StringBuilder();

    if (pInfo.TotalPages > 1)
    {
        TagBuilder tag;

        // previous link
        if (pInfo.CurrentPage > 1)
        {
            tag = new TagBuilder("a");
            tag.MergeAttribute("href", pageUrl(pInfo.CurrentPage - 1));
            tag.AddCssClass("Prev");
            tag.InnerHtml = "previous";

            result.AppendLine(tag.ToString());
        }

        // numbered links
        for (int i = 1; i <= pInfo.TotalPages; i++)
        {
            if (i == pInfo.CurrentPage)
            {
                tag = new TagBuilder("span");
            }
            else 
            {
                tag = new TagBuilder("a");
                tag.MergeAttribute("href", pageUrl(i));
            }

            tag.InnerHtml = i.ToString();

            result.AppendLine(tag.ToString());
        }

        // next page link
        if (pInfo.CurrentPage < pInfo.TotalPages)
        {
            tag = new TagBuilder("a");
            tag.MergeAttribute("href", pageUrl(pInfo.CurrentPage + 1));
            tag.AddCssClass("Next");
            tag.InnerHtml = "next";
            result.AppendLine(tag.ToString());
        }
    }

    return MvcHtmlString.Create(result.ToString());
}

现在在您看来,您会像

一样使用它
@Html.Paginator(pageInfo, pageId => Url.Action("Index", "Home", new { pageId }))