MVC, кнопка отправки которого была нажата

128

У меня есть две кнопки в моей форме MVC:

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

Как я узнаю из действия моего контроллера, какой из них был нажат?

Coppermill
источник
Почему бы просто не добавить события 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();
}
WDuffy
источник
13
Остерегайтесь проблем, которые локализация может привести к этому решению, к которому решение Дарина неприемлемо.
Ричард Салай
Два входа с одинаковым именем приводят к тому, что отправляется массив с одним элементом для каждого значения, а не с одним значением, как подразумевается. Поэтому я хотел бы сказать иначе, поскольку я надеялся / пытался использовать это, но это не работает.
Кристофер Кинг,
1
@RichardSzalay - не могли бы вы просто использовать <button type="submit" name="action" value="draft"> Internationalized Save Text </button>для целей i18n, чтобы строка, обращенная к пользователю, была настраиваемой, а имена элементов формы никогда не
открывались
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
Это не работает, если у вас есть многоязычная система, которая меняет значение кнопки в зависимости от языка.
Дэйв
Дэйв - Я не думаю, что кто-то запрограммировал бы такую ​​систему. Это похоже на локализацию имен ваших контроллеров или имен функций. Значение кнопки исключительно для использования на стороне сервера - это не отображается в любом месте и не должны быть локализованы.
NickG
20

вы можете идентифицировать свою кнопку с помощью тега имени, как показано ниже, вам нужно проверить это в своем контроллере

if (Request.Form["submit"] != null)
{
//Write your code here
}
else if (Request.Form["process"] != null)
{
//Write your code here
}
Кинджал Гохил
источник
это очень полезно в ситуациях, когда вы не хотите передавать имя кнопки в результат действия публикации.
yogihosting
в этом сценарии может быть сложнее имитировать класс Request в модульном тесте.
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
Фредрик Стигссон
источник
Это превосходное решение по сравнению со всем остальным, опубликованным, поскольку оно позволяет последовательно передавать очень сложные данные формы без настраиваемых наборов параметров в каждом действии, что позволяет легко настраивать логику контроллера для сложных форм. Престижность Фредрик :) Я предполагаю, что этот FormCollection будет передаваться в нескольких формах?
Stokely
Спасибо, Стокли. Вы можете вызвать этот метод из нескольких форм, если вы выполните вызов 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
    }
}

когда пользователь отправляет страницу с помощью одной из кнопок, только один из аргументов будет иметь значение. Думаю, это будет полезно для других.

Обновить

Это довольно старый ответ, и я пересматриваю свое мнение. возможно, приведенное выше решение подходит для ситуации, когда параметр передается в свойства модели. не беспокойтесь и выберите лучшее решение для вашего проекта.

AAAA
источник
Некоторая конструктивная критика: это хорошо покрыто существующими ответами на момент вашей публикации. Кроме того, это плохо масштабируется. HTML отправит обратно только то input[type=submit]значение, которое было инициировано, поэтому все они могут привязать модель к свойству с одним и тем же name(например action), а затем вы можете различать кнопки на основе valueэтой строки без необходимости вводить столько переменных в свою подпись , Пожалуйста, также подумайте о форматировании / отступах перед публикацией.
KyleMit
0

Не можете узнать с помощью Request.Form Collection? Если щелкнуть процесс, request.form ["процесс"] не будет пустым.

chugh97
источник
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)
       {
       .......
Leftware
источник
Это может сработать, но я предпочитаю параметр string submitзаписи string submit = Request.Form["Submit"];. Одним из самых больших преимуществ Razor Pages и / или MVC является удобочитаемость методов, иначе это мог бы быть PHP.
yzorg