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

Два входа с одинаковым именем приводят к тому, что отправляется массив с одним элементом для каждого значения, а не с одним значением, как подразумевается. Поэтому я хотел бы сказать иначе, поскольку я надеялся / пытался использовать это, но это не работает.
Кристофер Кинг,

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
    }
}

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

Обновить

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


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

0

Не можете узнать с помощью Request.Form Collection? Если щелкнуть процесс, request.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 Pages и / или MVC является удобочитаемость методов, иначе это мог бы быть PHP.
yzorg
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.