คุณเปลี่ยนเส้นทางไปยังเพจโดยใช้กริยา POST ได้อย่างไร?


133

เมื่อคุณโทรRedirectToActionภายในคอนโทรลเลอร์จะเปลี่ยนเส้นทางโดยอัตโนมัติโดยใช้ HTTP GET ฉันจะบอกอย่างชัดเจนให้ใช้ HTTP POST ได้อย่างไร

ฉันมีการดำเนินการที่ยอมรับทั้งคำขอ GET และ POST และฉันต้องการให้สามารถRedirectToActionใช้ POST และส่งค่าบางอย่างได้

แบบนี้:

this.RedirectToAction(
    "actionname",
    new RouteValueDictionary(new { someValue = 2, anotherValue = "text" })
);

ฉันต้องการให้someValueและanotherValueค่าถูกส่งโดยใช้ HTTP POST แทน GET ไม่มีใครรู้วิธีการทำเช่นนี้?


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

คำตอบ:


105

HTTP ไม่รองรับการเปลี่ยนเส้นทางไปยังเพจโดยใช้ POST เมื่อคุณเปลี่ยนเส้นทางไปที่ใดที่หนึ่งส่วนหัว "ตำแหน่ง" ของ HTTP จะบอกเบราว์เซอร์ว่าจะไปที่ใดและเบราว์เซอร์จะส่งคำขอ GET สำหรับหน้านั้น คุณอาจต้องเขียนโค้ดสำหรับเพจของคุณเพื่อยอมรับคำขอ GET และคำขอ POST


4
สงสัยว่าทำไมคำตอบของฉันถึงไม่ได้รับการยอมรับฉันคิดว่าสำนวนของฉันฟังดูดี :) จากนั้นอีกครั้งฉันอาจจะลำเอียงเล็กน้อยเกี่ยวกับเรื่องนี้ ...
Jason Bunting

14
แม้ว่าคำตอบนี้จะถูกต้อง แต่ก็ยังไม่สมบูรณ์ ดูคำตอบของ Jason Bunting ด้านล่างสำหรับวิธีแก้ปัญหาที่ดีขึ้นมาก
Adrian Grigore

160

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

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index() {
   // obviously these values might come from somewhere non-trivial
   return Index(2, "text");
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(int someValue, string anotherValue) {
   // would probably do something non-trivial here with the param values
   return View();
}

ที่ทำงานได้ง่ายและไม่มีธุรกิจตลกเกิดขึ้นจริง ๆ - สิ่งนี้ช่วยให้คุณรักษาความจริงที่ว่าอันที่สองยอมรับคำขอ HTTP POST เท่านั้น (ยกเว้นในอินสแตนซ์นี้ซึ่งอยู่ภายใต้การควบคุมของคุณอยู่ดี) และคุณไม่จำเป็นต้อง ใช้ TempData อย่างใดอย่างหนึ่งซึ่งเป็นลิงค์ที่คุณโพสต์ในคำตอบของคุณแนะนำ

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

หวังว่าจะช่วยได้


7
ใครจะรู้ว่าทำไมคุณถึงถูกลดคะแนน นี่เป็นวิธีการที่มีประโยชน์มาก
Peter J

2
นี่คือวิธีที่ฉันแก้ไขปัญหานี้เสมอเช่นกัน การลงคะแนนนี้ไม่สมเหตุสมผล
Adrian Grigore

39
ฉันโหวตให้แม้ว่าฉันไม่เห็นด้วยกับการเรียกคนงี่เง่าเมื่อคุณไม่รู้จักพวกเขา
Jim Schubert

3
ฉันไม่ได้เป็นผู้โหวตลดคะแนน แต่ข้อควรระวังคือหากคุณเรียกมุมมองด้วยชื่ออื่นหรือหากพารามิเตอร์มีความสำคัญค่าเหล่านั้นจะหายไป เหตุผลคือ URL จะแสดงพารามิเตอร์ action + ก่อนที่จะเปลี่ยนเส้นทางฝั่งเซิร์ฟเวอร์ สิ่งนี้อาจทำให้ผู้ใช้สับสนโดยเฉพาะอย่างยิ่งถ้าพวกเขารีเฟรชหน้าแล้วพบว่าตัวเองอยู่ที่หน้าก่อนหน้า (เนื่องจากการรีเฟรชใช้ URL เก่า) เทคนิคนี้มีความคล้ายคลึงกับเซิร์ฟเวอร์ของ asp.net เป็นหลักการโอนและควรใช้ความระมัดระวังเช่นเดียวกัน
AaronLS

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

21

ถ้าคุณต้องการส่งผ่านข้อมูลระหว่างสองการกระทำระหว่างการเปลี่ยนเส้นทางโดยไม่รวมข้อมูลใด ๆ ในสตริงแบบสอบถามให้ใส่โมเดลในวัตถุ TempData

หนังบู๊

TempData["datacontainer"] = modelData;

ดู

var modelData= TempData["datacontainer"] as ModelDataType; 

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

ดังนั้นสถานการณ์เดียวที่การใช้ TempData จะทำงานได้อย่างน่าเชื่อถือคือเมื่อคุณเปลี่ยนเส้นทาง


12

ลองอันนี้

return Content("<form action='actionname' id='frmTest' method='post'><input type='hidden' name='someValue' value='" + someValue + "' /><input type='hidden' name='anotherValue' value='" + anotherValue + "' /></form><script>document.getElementById('frmTest').submit();</script>");

4
เกลียด แต่ก็รัก :)
divinci

แฮ็คดังกล่าว แต่เป็นวิธีเดียวที่ฉันสามารถทำสิ่งที่ต้องการได้โดยไม่ละเมิด DRY หรือเดินสายใหม่ทั้งหมด! ขอบคุณ!
jamheadart

6

ฉันต้องการขยายคำตอบของ Jason Bunting

แบบนี้

ActionResult action = new SampelController().Index(2, "text");
return action;

และอีไลจะมาที่นี่เพื่อขอแนวคิดเกี่ยวกับวิธีทำให้เป็นตัวแปรทั่วไป

สามารถรับคอนโทรลเลอร์ได้ทุกประเภท


2
คุณไม่ควรสร้างอินสแตนซ์ไปยังคอนโทรลเลอร์ด้วยnew ...()เพราะคุณจะสูญเสียRequestContext- หากคุณอยู่ในคอนโทรลเลอร์เดียวกันอยู่แล้วคุณอาจไม่จำเป็นต้องสร้างอินสแตนซ์ใหม่ มิฉะนั้นให้ทำตามวิธีต่อไปนี้SampelController sampleController = DependencyResolver.Current.GetService<SampelController>(): sampleController.ControllerContext = new ControllerContext(Request.RequestContext, sampleController);แล้วคุณสามารถreturn sampleController.Index(2, "text");บอกใบ้ :)
Matthias Burger
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.