Натиснуто MVC, яке натискає кнопку подання


128

У мене на MVC-формі є дві кнопки:

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

З моєї дії Controller як я дізнаюся, на кого натискали?


Чому б не додати події 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" />

Тоді у вашому контролері отримайте значення подання. Лише натиснута кнопка передасть значення.

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
Остерігайтеся тих питань, які локалізація може принести до цього рішення, до яких рішення Даріна не піддається.
Річард Салай

Два входи з однаковою назвою призводять до того, що масив розміщується з одним елементом для кожного значення, а не одним значенням, як мається на увазі. Тож я хотів би сказати інакше, оскільки сподівався / намагався використати це, але це не працює.
Крістофер Кінг

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

Це руйнується, якщо у вас багатомовна система, яка змінює значення кнопки відповідно до мови.
Дейв Tapson

Дейв - Я не думаю, що хтось би кодував таку систему. Це як локалізація імен контролера чи імен функцій. Значення кнопки виключно для використання на стороні сервера - це не відображається в будь-якому місці і не повинні бути локалізовані.
NickG

20

ви можете ідентифікувати свою кнопку звідти тегом імені, як показано нижче. Потрібно перевірити так, як у вашому контролері

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

це дуже корисно в ситуаціях, коли ви не хочете передати назву кнопки після результату дії після публікації.
йогіхостінг

у цьому випадку може бути складніше знущатися з класу Request в одиничному тесті.
Муфлікс

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спеціальні атрибути, які дозволяють розрізняти кнопки подання. Насправді досить приємна ідея.
Пройшов кодування

1
І якби ви Arnis L.дотримувались тієї ж поради, ви, можливо, помітили, що він надавав саме таку посилання 4 роками раніше:>
Пройшло кодування

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 проходитиме в декількох формах?
Стоклей

Дякую Стоуклі. Ви можете викликати цей метод з декількох форм, якщо ви здійснюєте ajax-дзвінок, тоді ви можете включати багато форм в один і той же FormCollection.
Фредрік Стігссон

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 абсолютно правильне", і воно працює чудово, але моє рішення (насправді не моє) буде використовуватися в інших елементах, і це робить презентаційний шар більш незалежним від контролера (тому що ваш контролер залежить від "значення", яке використовується для відображення мітки кнопки, ця функція важлива для інших мов.).

Ось моє рішення, дайте їм різні назви:

<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? Якщо натиснути процес, запит.form ["процес"] не буде порожнім


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 та / або MVC є читабельність методів, інакше це може бути PHP.
yzorg
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.