Menghasilkan Url yang benar di dalam Metode HtmlHelper

Saya telah membangun metode Pembantu HTML kasar dengan tujuan membuat dua tautan penomoran halaman (Berikutnya dan Sebelumnya).

Di bawah ini adalah kode untuk ViewModel (DTO) yang diteruskan ke Metode Helper:

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); }
    }
}

Dan berikut ini kode HTML Helper Method :

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());
}

Kombinasi kode di atas sepertinya berfungsi, tetapi hanya dari beranda, jika saya klik tautan Sebelumnya [ localhost:xxxx/page/2 ], dan masuk ke halaman 2, maka tautannya menjadi [ localhost:xxxx/page/page/ 2 ].

Perutean saya terlihat sebagai berikut

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
);

Seperti yang Anda lihat, halaman kata sekarang diduplikasi. Saya dapat memikirkan cara untuk memperbaiki masalah ini, dan itu adalah dengan memerintahkannya untuk menghasilkan ActionLink dari root, dan membuat URL saya seperti itu, tapi saya tidak yakin bagaimana melakukannya di pembantu HTML, dan apa yang cara terbaik untuk melakukannya adalah.


person J86    schedule 20.12.2011    source sumber


Jawaban (1)


Cara yang baik adalah dengan mendefinisikan pembantu yang mengambil delegasi Func<int, string> yang dapat meneruskan nomor halaman dan mengembalikan string URL yang dihasilkan. Dengan cara ini, pembantu paginator tidak terikat pada perutean tertentu dan dapat digunakan kembali di seluruh aplikasi Anda dengan mudah.

Sesuatu seperti

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());
}

Sekarang menurut Anda, Anda akan menggunakannya seperti itu

@Html.Paginator(pageInfo, pageId => Url.Action("Index", "Home", new { pageId }))
person Russ Cam    schedule 20.12.2011
comment
+1, saya baru saja akan memposting jawaban yang terlihat hampir sama dengan ini. Satu-satunya hal yang akan saya sebutkan selain itu adalah bagaimana membuat URL terlihat seperti /Page2 VS /?page=2 dengan penambahan rute baru. - person Jesse; 20.12.2011
comment
@Jesse - ya, bagaimana perutean didefinisikan adalah keseluruhan ketel ikan lainnya :) - person Russ Cam; 20.12.2011
comment
Terima kasih atas balasan cepat Russ Cam. Dua hal, bisakah Anda menjelaskan secara singkat cara kerja [ Fun‹int, string› ]? Saya melihat dokumentasi Microsoft untuk Delegasi, tetapi sangat rumit untuk dipahami. :( Saya juga telah menyalin kode Anda dan sekarang tautan saya terlihat seperti ini [localhost:xxxx/?page=2] alih-alih [localhost:xxxx/page/2] ini! Perutean saya sudah diatur seperti ini. - person J86; 20.12.2011
comment
@Ciwan - Func<int, string> seperti tanda tangan metode untuk metode yang mengambil int dan mengembalikan string. Dalam contoh penggunaan di atas, kita meneruskan ekspresi lambda sebagai argumen kedua untuk parameter Func<int, string> yang digunakan metode Paginator. Ekspresi lambda mengambil parameter page, meneruskannya ke Url.Action() yang mengembalikan string (URL yang dihasilkan). Tipe parameter page diketik dengan kuat menjadi int karena ini disimpulkan dari konversi implisit ekspresi lambda ke delegasi Func<int, string> yang diketik dengan kuat. Jadi... - person Russ Cam; 20.12.2011
comment
int i yang bertambah dari loop di dalam metode Paginator diteruskan ke metode Func<int,string> yang diteruskan ke metode Paginator, yang terikat ke parameter page ekspresi lambda dan mengembalikan URL. Apakah itu menjelaskannya? - person Russ Cam; 20.12.2011
comment
@Ciwan - sekarang saya telah melihat rute Anda, saya telah memperbarui contoh penggunaan sehingga Anda sekarang akan mendapatkan URL yang dihasilkan yang Anda harapkan - person Russ Cam; 20.12.2011
comment
Terima kasih banyak Russ Cam. Ini berfungsi dengan baik, dan terlebih lagi, saya sekarang tahu apa yang dilakukan Func‹int, string›, berkat penjelasan Anda. - person J86; 21.12.2011
comment
@Ciwan - Senang membantu :) Sebaiknya luangkan waktu untuk melihat delegasi Action dan Func (termasuk variasi umum), serta ekspresi lambda, karena digunakan di semua tempat di LINQ. Jika Anda benar-benar ingin menguasainya, saya akan merekomendasikan C# in Depth yang luar biasa dari Jon Skeet. Jika Anda mendaftar ke Manning 2012 Countdown, penawaran tersebut mungkin muncul - deals.manningpublications.com/countdown2012. html :) - person Russ Cam; 21.12.2011
comment
Terima kasih Russ, saya sudah mendaftar untuk CountDown, dan saya pasti akan mendapatkan buku itu. Terima kasih. :) - person J86; 21.12.2011