วิธี RedirectToAction ใน ASP.NET MVC โดยไม่สูญเสียข้อมูลคำขอ


123

การใช้ ASP.NET MVC มีสถานการณ์ (เช่นการส่งแบบฟอร์ม) ที่อาจต้องใช้ไฟล์RedirectToAction.

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

เนื่องจากฉันต้องการให้แบบฟอร์มมีPOSTข้อมูล ed เดิมเพื่อความสะดวกของผู้ใช้และวัตถุประสงค์ในการตรวจสอบความถูกต้องฉันจะส่งข้อมูลผ่านทางRedirectToAction()? ถ้าฉันใช้พารามิเตอร์ viewData พารามิเตอร์ของฉันPOSTจะเปลี่ยนเป็นGETพารามิเตอร์


นี่คือคำถามที่คล้ายกัน (ในหัวข้อเดียวกัน) แต่แตกต่างจากคำถามนี้ อย่างไรก็ตามผู้ที่สนใจคำถามนี้ยังคงเป็นที่สนใจ: http://stackoverflow.com/questions/129335/how-do-you-redirecttoaction-using-post-intead-of-get
Chris Pietschmann

ทำไมคุณไม่เพียงแค่คืนมุมมองเดิมหากมีข้อผิดพลาด โดยปกติแล้ว RedirectToAction จะถูกเรียกว่า Model นั้นถูกต้อง - หรือฉันขาดอะไรไป?!
niico

คำตอบ:


81

วิธีแก้ปัญหาคือใช้คุณสมบัติ TempData เพื่อจัดเก็บคอมโพเนนต์คำขอที่ต้องการ

ตัวอย่างเช่น:

public ActionResult Send()
{
    TempData["form"] = Request.Form;
    return this.RedirectToAction(a => a.Form());
}

จากนั้นในการดำเนินการ "แบบฟอร์ม" ของคุณคุณสามารถไป:

public ActionResult Form()
{
    /* Declare viewData etc. */

    if (TempData["form"] != null)
    {
        /* Cast TempData["form"] to 
        System.Collections.Specialized.NameValueCollection 
        and use it */
    }

    return View("Form", viewData);
}

1
RedirectToAction (a => a.Form ()) ไม่ได้รวบรวมให้ฉันใช้ MVCv2 คุณใช้ MVCv3 หรือไม่
ChrisAnnODell

1
นี่เป็นช่วงก่อน MVC1 (2008) ฉันเชื่อว่า lambdas ถูกลบออกไปในบางขั้นตอน (มีโครงการ codeplex MVCContrib ที่แนะนำพวกเขาอีกครั้งแม้ว่าคุณอาจใช้แอตทริบิวต์ตัวช่วยในขั้นตอนนั้นได้เช่นกัน: stackoverflow.com/questions/1936/… ) ใน mvc2 คุณควรจะไป RedirectToAction ("Form") ได้เช่นตั้งชื่อเป็นสตริงแม้ว่าฉันจะจำได้อย่างหลวม ๆ ว่า MVC 2 หรือ 3 ได้แนะนำแอตทริบิวต์ตัวช่วยที่คล้ายกับใน MVCContrib หากคุณต้องการค้นหา
Matt Mitchell

37

โปรดทราบว่า TempData จัดเก็บการรวบรวมแบบฟอร์มในเซสชัน หากคุณไม่ชอบพฤติกรรมนั้นคุณสามารถใช้อินเทอร์เฟซ ITempDataProvider ใหม่และใช้กลไกอื่น ๆ ในการจัดเก็บข้อมูลชั่วคราว ฉันจะไม่ทำอย่างนั้นเว้นแต่คุณจะรู้ข้อเท็จจริง (ผ่านการวัดและการทำโปรไฟล์) ว่าการใช้สถานะเซสชันกำลังทำร้ายคุณ



8

มีอีกวิธีหนึ่งที่หลีกเลี่ยง tempdata รูปแบบที่ฉันชอบเกี่ยวข้องกับการสร้าง 1 การกระทำสำหรับทั้งการเรนเดอร์ดั้งเดิมและการเรนเดอร์ซ้ำของฟอร์มที่ไม่ถูกต้อง มันจะเป็นดังนี้:

var form = new FooForm();

if (request.UrlReferrer == request.Url)
{
     // Fill form with previous request's data
}

if (Request.IsPost())
{
     if (!form.IsValid)
     {
         ViewData["ValidationErrors"] = ...
     } else {
         // update model
         model.something = foo.something;
         // handoff to post update action
         return RedirectToAction("ModelUpdated", ... etc);
     }
}

// By default render 1 view until form is a valid post
ViewData["Form"] = form;
return View();

นั่นคือรูปแบบไม่มากก็น้อย pseudoy เล็กน้อย ด้วยวิธีนี้คุณสามารถสร้าง 1 มุมมองเพื่อจัดการการแสดงผลฟอร์มแสดงค่าอีกครั้ง (เนื่องจากฟอร์มจะเต็มไปด้วยค่าก่อนหน้า) และแสดงข้อความแสดงข้อผิดพลาด

เมื่อโพสต์ไปยังการดำเนินการนี้หากถูกต้องจะโอนการควบคุมไปยังการดำเนินการอื่น

ฉันพยายามทำให้รูปแบบนี้ง่ายขึ้นในกรอบการตรวจสอบความถูกต้อง. netในขณะที่เราสร้างการสนับสนุน MVC


ฉันใช้ TempData เช่นกันปัญหาตามที่ฉันเข้าใจด้วยวิธีแก้ปัญหาของคุณ Deeno คือหากผู้ใช้รีเฟรชหน้าหลังจากโพสต์ข้อมูลที่ไม่ถูกต้องพวกเขาจะได้รับการยืนยัน "คุณต้องการส่งข้อมูลแบบฟอร์มอีกครั้ง" การใช้โซลูชัน TempData ตามที่ MattMitchell บอกจะช่วยขจัดปัญหานี้
user10479

เย็น. ดูเหมือนจะมีคนสังเกตเห็นแนวคิดพื้นฐานนี้ในตัวอย่างที่ 5 ด้วย
Matt Mitchell

2

หากคุณต้องการส่งข้อมูลไปยังการดำเนินการเปลี่ยนเส้นทางวิธีที่คุณสามารถใช้ได้คือ:

return RedirectToAction("ModelUpdated", new {id = 1});
// The definition of the action method like  public ActionResult ModelUpdated(int id);

0

TempData เป็นโซลูชันที่เก็บข้อมูลจากการกระทำไปสู่การกระทำ

Employee employee = new Employee
                {
                        EmpID = "121",
                        EmpFirstName = "Imran",
                        EmpLastName = "Ghani"
                };
                TempData["Employee"] = employee;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.