การสร้าง URL ที่ถูกต้องภายในวิธี HtmlHelper

ฉันได้สร้างวิธีตัวช่วย HTML แบบหยาบโดยมีจุดประสงค์เพื่อสร้างลิงก์แบ่งหน้าสองลิงก์ (ถัดไปและก่อนหน้า)

ด้านล่างนี้เป็นรหัสสำหรับ 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());
}

ดูเหมือนว่าการรวมกันของโค้ดข้างต้นจะใช้งานได้ แต่เฉพาะจากหน้าแรกเท่านั้น ถ้าฉันคลิกลิงก์ก่อนหน้า [ 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
);

อย่างที่คุณเห็นตอนนี้คำว่าหน้าซ้ำแล้ว ฉันสามารถคิดวิธีแก้ไขปัญหานี้ได้ และนั่นคือบอกให้สร้าง ActionLink จากรูท และสร้าง URL ของฉันแบบนั้น แต่ฉันไม่แน่ใจว่าจะต้องทำอย่างไรในตัวช่วย HTML และสิ่งที่ วิธีที่ดีที่สุดที่จะทำคือ


person J86    schedule 20.12.2011    source แหล่งที่มา


คำตอบ (1)


วิธีที่ดีคือการกำหนดตัวช่วยที่รับผู้รับมอบสิทธิ์ Func<int, string> ที่สามารถส่งผ่านหมายเลขหน้าและส่งกลับสตริง URL ที่สร้างขึ้น ด้วยวิธีนี้ ตัวช่วยแบ่งหน้าจะไม่ผูกกับเส้นทางใดๆ และสามารถนำกลับมาใช้ใหม่ทั่วทั้งแอปพลิเคชันของคุณได้อย่างง่ายดาย

สิ่งที่ต้องการ

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 }))
person Russ Cam    schedule 20.12.2011
comment
+1 ฉันกำลังจะโพสต์คำตอบที่ดูเกือบจะเหมือนกันนี้ สิ่งเดียวที่ฉันจะพูดถึงเพิ่มเติมคือวิธีทำให้ URL ดูเหมือน /Page2 VS /?page=2 ด้วยการเพิ่มเส้นทางใหม่ - person Jesse; 20.12.2011
comment
@Jesse - ใช่แล้ว วิธีการกำหนดเส้นทางคือปลากาต้มน้ำตัวอื่น :) - person Russ Cam; 20.12.2011
comment
ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว Russ Cam สองสิ่ง คุณช่วยอธิบายสั้น ๆ ว่า [ Fun‹int, string› ] ทำงานอย่างไร ฉันดูเอกสารของ Microsoft สำหรับ Delegate แต่มันซับซ้อนมากที่จะเข้าใจ :( นอกจากนี้ ฉันได้คัดลอกโค้ดของคุณแล้ว และตอนนี้ลิงก์ของฉันมีลักษณะเช่นนี้ [localhost:xxxx/?page=2] แทนที่จะเป็น [localhost:xxxx/page/2] ! การกำหนดเส้นทางของฉันคือการตั้งค่า ถูกใจสิ่งนี้ - person J86; 20.12.2011
comment
@Ciwan - Func<int, string> เป็นเหมือนลายเซ็นวิธีการสำหรับวิธีที่รับ int และส่งคืน string ในตัวอย่างการใช้งานข้างต้น เราจะส่งนิพจน์แลมบ์ดาเป็นอาร์กิวเมนต์ที่สองสำหรับพารามิเตอร์ Func<int, string> ที่เมธอด Paginator ใช้ นิพจน์แลมบ์ดาใช้พารามิเตอร์ page ส่งต่อไปยัง Url.Action() ซึ่งส่งคืนสตริง (URL ที่เป็นผลลัพธ์) ประเภทพารามิเตอร์ page ถูกพิมพ์อย่างยิ่งให้เป็น int เนื่องจากอนุมานได้จากการแปลงนิพจน์แลมบ์ดาโดยนัยไปเป็นผู้รับมอบสิทธิ์ที่พิมพ์อย่างยิ่ง Func<int, string> ดังนั้น... - person Russ Cam; 20.12.2011
comment
int i ที่เพิ่มขึ้นจากการวนซ้ำภายในเมธอด Paginator จะถูกส่งผ่านไปยังเมธอด Func<int,string> ที่ส่งผ่านไปยังเมธอด Paginator ซึ่งเชื่อมโยงกับพารามิเตอร์ page ของนิพจน์แลมบ์ดาและส่งกลับ URL นั่นอธิบายมันได้ไหม? - person Russ Cam; 20.12.2011
comment
@Ciwan - ตอนนี้ฉันเห็นเส้นทางของคุณแล้ว ฉันได้อัปเดตการใช้งานตัวอย่าง ดังนั้นคุณควรได้รับ URL ที่สร้างขึ้นตามที่คุณคาดหวัง - person Russ Cam; 20.12.2011
comment
ขอบคุณมาก รัส แคม มันใช้งานได้ดี และยิ่งไปกว่านั้น ตอนนี้ฉันรู้แล้วว่า Func‹int, string› ทำอะไรได้บ้าง ขอบคุณคำอธิบายของคุณ - person J86; 21.12.2011
comment
@Ciwan - ยินดีให้ความช่วยเหลือ :) คุ้มค่าที่สละเวลาดูผู้ได้รับมอบหมาย Action และ Func (รวมถึงรูปแบบทั่วไป) รวมถึงนิพจน์แลมบ์ดาเนื่องจากมีการใช้ทั่วทุกแห่งใน LINQ หากคุณต้องการที่จะบ่นพวกเขาจริงๆ ฉันขอแนะนำ C# ที่ยอดเยี่ยมของ Jon Skeet ในเชิงลึก หากคุณสมัครเข้าร่วม Manning 2012 Countdown อาจได้รับข้อเสนอ - deals.manningpublications.com/countdown2012 HTML :) - person Russ Cam; 21.12.2011
comment
ขอบคุณรัส ฉันสมัคร CountDown แล้ว และจะได้หนังสือเล่มนั้นแน่นอน ขอบคุณ. :) - person J86; 21.12.2011