MVC ซึ่งกดปุ่มส่งแล้ว


128

ฉันมีสองปุ่มในแบบฟอร์ม MVC ของฉัน:

<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

จากการกระทำของคอนโทรลเลอร์ฉันจะรู้ได้อย่างไรว่าอันไหนถูกกด?


ทำไมไม่เพิ่มเหตุการณ์ onclick ลงในปุ่มเหล่านี้ที่ไปที่การโทร AJAX ของตัวเองซึ่งจะไปยังวิธีการที่เหมาะสม ได้แก่ : <input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" />?
ragerory

คำตอบ:


169

ตั้งชื่อปุ่มส่งทั้งสองปุ่มเหมือนกัน

<input name="submit" type="submit" id="submit" value="Save" />
<input name="submit" type="submit" id="process" value="Process" />

จากนั้นในคอนโทรลเลอร์ของคุณจะได้รับค่า submit เฉพาะปุ่มที่คลิกเท่านั้นที่จะส่งผ่านค่าของมัน

public ActionResult Index(string submit)
{
    Response.Write(submit);
    return View();
}

แน่นอนคุณสามารถประเมินค่านั้นเพื่อดำเนินการต่างๆด้วยสวิตช์บล็อก

public ActionResult Index(string submit)
{
    switch (submit)
    {
        case "Save":
            // Do something
            break;
        case "Process":
            // Do something
            break;
        default:
            throw new Exception();
            break;
    }

    return View();
}

13
ระวังปัญหาที่การแปลเป็นภาษาท้องถิ่นอาจนำมาสู่การแก้ปัญหานี้ซึ่งวิธีการแก้ปัญหาของ Darin ไม่ได้รับความหวั่นไหว
Richard Szalay

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

1
@RichardSzalay - คุณใช้<button type="submit" name="action" value="draft"> Internationalized Save Text </button>เพื่อจุดประสงค์ i18n ไม่ได้หรือไม่ดังนั้นสตริงที่ผู้ใช้เผชิญหน้าจึงสามารถปรับแต่งได้และชื่อองค์ประกอบแบบฟอร์มจะไม่ถูกเปิดเผยโดยตรงกับผู้ใช้ (ซึ่งเป็นเลขแปลกและในตัวมันเอง)
KyleMit

48
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

และในการดำเนินการควบคุมของคุณ:

public ActionResult SomeAction(string submit)
{
    if (!string.IsNullOrEmpty(submit))
    {
        // Save was pressed
    }
    else
    {
        // Process was pressed
    }
}

1
ฉันคิดว่าสามารถเพิ่มปุ่มต่างๆได้โดยเพียงแค่เพิ่มลงในรายการพารามิเตอร์และตั้งชื่อให้ถูกต้อง ทางออกที่ดี!
GONeale

35

นี่เป็นคำตอบที่ดีกว่าดังนั้นเราสามารถมีทั้งข้อความและค่าสำหรับปุ่ม:

http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx

</p>
<button name="button" value="register">Register</button>
<button name="button" value="cancel">Cancel</button>
</p>

และตัวควบคุม:

public ActionResult Register(string button, string userName, string email, string password, string confirmPassword)
{
if (button == "cancel")
    return RedirectToAction("Index", "Home");
...

เรียกสั้น ๆ ว่าปุ่ม SUBMIT แต่คุณเลือกชื่อโดยใช้แอตทริบิวต์ name ซึ่งมีประสิทธิภาพมากยิ่งขึ้นเนื่องจากคุณไม่ได้ผูกพันกับชื่อส่งหรือปุ่มในพารามิเตอร์วิธีการควบคุมคุณสามารถเรียกได้ตามที่คุณต้องการ ...


ขอบคุณครับนี่คือสิ่งที่ผมต้องการ
oHoodie

สิ่งนี้จะหยุดพักหากคุณมีระบบหลายภาษาที่เปลี่ยนค่าของปุ่มตามภาษา
Dave Tapson

Dave - ฉันไม่คิดว่าจะมีใครเขียนโค้ดระบบแบบนั้น นั่นเหมือนกับการแปลชื่อคอนโทรลเลอร์หรือชื่อฟังก์ชันของคุณ ค่าของปุ่มสำหรับใช้ฝั่งเซิร์ฟเวอร์เท่านั้น - มันไม่แสดงได้ทุกที่และไม่จำเป็นต้องได้รับการแปลเป็นภาษาท้องถิ่น
NickG

20

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

if (Request.Form["submit"] != null)
{
//Write your code here
}
else if (Request.Form["process"] != null)
{
//Write your code here
}

สิ่งนี้มีประโยชน์มากในสถานการณ์ที่คุณไม่ต้องการส่งชื่อปุ่มไปยังผลลัพธ์ของโพสต์
yogihosting

ในสถานการณ์นี้อาจมีความซับซ้อนมากขึ้นในการจำลองคลาสคำขอในการทดสอบหน่วย
Muflix

6

นี่เป็นวิธีที่ดีและง่ายมากในการทำตามคำแนะนำโดยใช้ MultiButtonAttribute ที่กำหนดเอง:

http://blog.maartenballiauw.be/post/2009/11/26/Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx

สรุปให้ทำปุ่มส่งของคุณดังนี้:

<input type="submit" value="Cancel" name="action" />
<input type="submit" value="Create" name="action" /> 

การกระทำของคุณเช่นนี้:

[HttpPost]
[MultiButton(MatchFormKey="action", MatchFormValue="Cancel")]
public ActionResult Cancel()
{
    return Content("Cancel clicked");
}

[HttpPost]
[MultiButton(MatchFormKey = "action", MatchFormValue = "Create")]
public ActionResult Create(Person person)
{
    return Content("Create clicked");
} 

และสร้างคลาสนี้:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultiButtonAttribute : ActionNameSelectorAttribute
{
    public string MatchFormKey { get; set; }
    public string MatchFormValue { get; set; }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        return controllerContext.HttpContext.Request[MatchFormKey] != null &&
            controllerContext.HttpContext.Request[MatchFormKey] == MatchFormValue;
    }
}

1
ควรสรุปลิงก์อ้างอิง (สำหรับวันที่บล็อกหายไป) โดยสรุปว่าบล็อกสนับสนุนให้มีMultiButtonAttributeแอตทริบิวต์ที่กำหนดเองเพื่อให้สามารถแยกความแตกต่างระหว่างปุ่มส่ง จริงๆแล้วเป็นความคิดที่ดีทีเดียว
Gone Coding

1
และหากArnis L.ปฏิบัติตามคำแนะนำเดียวกันคุณอาจสังเกตเห็นว่าเขาให้ลิงค์เดียวกันเมื่อ 4 ปีก่อน:>
Gone Coding

3
// Buttons
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

// Controller
[HttpPost]
public ActionResult index(FormCollection collection)
{
    string submitType = "unknown";

    if(collection["submit"] != null)
    {
        submitType = "submit";
    }
    else if (collection["process"] != null)
    {
        submitType = "process";
    }

} // End of the index method

นี่เป็นวิธีแก้ปัญหาที่เหนือกว่าสำหรับทุกสิ่งที่โพสต์เนื่องจากช่วยให้สามารถส่งผ่านข้อมูลฟอร์มที่ซับซ้อนมากได้อย่างต่อเนื่องโดยไม่มีชุดพารามิเตอร์ที่กำหนดเองในแต่ละการดำเนินการทำให้ตรรกะของคอนโทรลเลอร์สามารถปรับแต่งได้อย่างมากสำหรับรูปแบบที่ซับซ้อน Kudos Fredrik :) ฉันคิดว่า FormCollection นี้จะส่งผ่านในหลายรูปแบบ?
Stokely

ขอบคุณ Stokely คุณสามารถเรียกเมธอดนี้ได้จากหลายรูปแบบหากคุณทำการโทรแบบ ajax คุณสามารถรวมหลายรูปแบบไว้ใน FormCollection เดียวกัน
Fredrik Stigsson

3

เพื่อให้ง่ายขึ้นฉันจะบอกว่าคุณสามารถเปลี่ยนปุ่มของคุณดังต่อไปนี้:

<input name="btnSubmit" type="submit" value="Save" />
<input name="btnProcess" type="submit" value="Process" />

ตัวควบคุมของคุณ:

public ActionResult Create(string btnSubmit, string btnProcess)
{
    if(btnSubmit != null)
       // do something for the Button btnSubmit
    else 
       // do something for the Button btnProcess
}

2

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

นี่คือทางออกของฉันตั้งชื่อให้ต่างกัน:

<input type="submit" name="buttonSave" value="Save"/>
<input type="submit" name="buttonProcess" value="Process"/>
<input type="submit" name="buttonCancel" value="Cancel"/>

และคุณต้องระบุชื่อของปุ่มเป็นอาร์กิวเมนต์ในการดำเนินการดังต่อไปนี้:

public ActionResult Register(string buttonSave, string buttonProcess, string buttonCancel)
{
    if (buttonSave!= null)
    {
        //save is pressed
    }
    if (buttonProcess!= null)
    {
        //Process is pressed
    }
    if (buttonCancel!= null)
    {
        //Cancel is pressed
    }
}

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

ปรับปรุง

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


คำวิจารณ์เชิงสร้างสรรค์บางประการ: คำตอบนี้ครอบคลุมถึงคำตอบที่คุณโพสต์ไว้ นอกจากนี้ยังปรับขนาดได้ไม่ดี HTML จะโพสต์เฉพาะinput[type=submit]ค่าที่ถูกเรียกกลับเท่านั้นดังนั้นโมเดลทั้งหมดจึงสามารถเชื่อมโยงกับคุณสมบัติที่มีคุณสมบัติเดียวกันname(เช่นaction) จากนั้นคุณสามารถแยกความแตกต่างของปุ่มตามvalueสตริงนั้นโดยไม่จำเป็นต้องแนะนำตัวแปรจำนวนมากในลายเซ็นของคุณ . โปรดใช้เวลาในการพิจารณาเกี่ยวกับการจัดรูปแบบ / การเยื้องก่อนโพสต์
KyleMit

0

คุณไม่สามารถค้นหาโดยใช้ Request.Form Collection ได้หรือไม่? ถ้ากระบวนการถูกคลิก request.form ["process"] จะไม่ว่างเปล่า


0

ตั้งชื่อให้กับทั้งสองปุ่มและรับค่าจากแบบฟอร์ม

<div>
   <input name="submitButton" type="submit" value="Register" />
</div>

<div>
   <input name="cancelButton" type="submit" value="Cancel" />
</div>

ด้านคอนโทรลเลอร์:

public ActionResult Save(FormCollection form)
{
 if (this.httpContext.Request.Form["cancelButton"] !=null)
 {
   // return to the action;
 }

else if(this.httpContext.Request.Form["submitButton"] !=null)
 {
   // save the oprtation and retrun to the action;
 }
}

0

ในหน้า Core 2.2 Razor ไวยากรณ์นี้ใช้งานได้:

    <button type="submit" name="Submit">Save</button>
    <button type="submit" name="Cancel">Cancel</button>
public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
        return Page();
    var sub = Request.Form["Submit"];
    var can = Request.Form["Cancel"];
    if (sub.Count > 0)
       {
       .......

มันอาจได้ผล แต่ฉันชอบพารามิเตอร์string submitเทียบกับการเขียนstring submit = Request.Form["Submit"];มากกว่า ประโยชน์ที่ใหญ่ที่สุดอย่างหนึ่งของ Razor Pages และ / หรือ MVC คือความสามารถในการอ่านวิธีการไม่เช่นนั้นอาจเป็น PHP
yzorg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.