Как вы обрабатываете несколько кнопок отправки в ASP.NET MVC Framework? - PullRequest
699 голосов
/ 14 января 2009

Есть ли какой-нибудь простой способ обработки нескольких кнопок отправки из одной формы? Пример:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>

Есть идеи, как это сделать в бета-версии ASP.NET Framework? Все примеры, на которые я гуглил, содержат отдельные кнопки.

Ответы [ 35 ]

11 голосов
/ 22 декабря 2011

Вот что лучше всего подходит для меня:

<input type="submit" value="Delete" name="onDelete" />
<input type="submit" value="Save" name="onSave" />


public ActionResult Practice(MyModel model, string onSave, string onDelete)
{
    if (onDelete != null)
    {
        // Delete the object
        ...
        return EmptyResult();
    }

    // Save the object
    ...
    return EmptyResult();
}
9 голосов
/ 27 февраля 2014

Если ваш браузер поддерживает формирование атрибутов для кнопок ввода (IE 10+, не уверен в других браузерах), то должно работать следующее:

@using (Html.BeginForm()){
    //put form inputs here

<input id="sendBtn" value="Send" type="submit" formaction="@Url.Action("Name Of Send Action")" />

<input id="cancelBtn" value="Cancel" type="submit" formaction="@Url.Action("Name of Cancel Action") />

}
9 голосов
/ 08 ноября 2011

Если у вас нет ограничений на использование HTML 5, вы можете использовать тег <button> с атрибутом formaction:

<form action="demo_form.asp" method="get">
   First name: <input type="text" name="fname" /><br />
   Last name: <input type="text" name="lname" /><br />
   <button type="submit">Submit</button><br />
   <button type="submit" formaction="demo_admin.asp">Submit as admin</button>
</form>

Ссылка: http://www.w3schools.com/html5/att_button_formaction.asp

9 голосов
/ 30 апреля 2014

Я также сталкивался с этой «проблемой», но нашел довольно логичное решение, добавив атрибут name. Я не могу вспомнить, чтобы эта проблема возникла на других языках.

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

  • ...
  • Если форма содержит более одной кнопки отправки, успешной будет только активированная кнопка отправки.
  • ...

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

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="send" value="Send" />
<input type="submit" name="cancel" value="Cancel" />
<input type="submit" name="draft" value="Save as draft" />
<% Html.EndForm(); %>`

На принимающей стороне вам нужно будет только проверить, не является ли какой-либо из ваших известных типов отправки null

public ActionResult YourAction(YourModel model) {

    if(Request["send"] != null) {

        // we got a send

    }else if(Request["cancel"]) {

        // we got a cancel, but would you really want to post data for this?

    }else if(Request["draft"]) {

        // we got a draft

    }

}
8 голосов
/ 20 мая 2015

Есть три способа решения вышеуказанной проблемы

  1. HTML-путь
  2. Jquery way
  3. Способ «ActionNameSelectorAttribute»

Ниже приведено видео, в котором наглядно представлены все три подхода.

https://www.facebook.com/shivprasad.koirala/videos/vb.100002224977742/809335512483940

HTML-путь: -

В HTML-формате нам нужно создать две формы и поместить кнопку «Отправить» внутри каждой из форм. И действие каждой формы будет указывать на различные / соответствующие действия. Ниже показан код, который первая форма публикует в «Action1», а вторая - в «Action2» в зависимости от того, какая кнопка «Отправить» нажата.

<form action="Action1" method=post>
<input type=”submit” name=”Submit1”/>
</form>

<form action="Action2" method=post>
<input type=”submit” name=”Submit2”>
</form>

Ajax way: -

В случае, если вы любитель Ajax, эта вторая опция вас больше возбудит. Ajax-способом мы можем создать две разные функции «Fun1» и «Fun1», см. Код ниже. Эти функции будут выполнять вызовы Ajax с использованием JQUERY или любой другой среды. Каждая из этих функций связана с событиями «OnClick» кнопки «Отправить». Каждая из этих функций вызывает соответствующие имена действий.

<Script language="javascript">
function Fun1()
{
$.post(“/Action1”,null,CallBack1);
}
function Fun2()
{
$.post(“/Action2”,null,CallBack2);
}
</Script>

<form action="/Action1" method=post>
<input type=submit name=sub1 onclick=”Fun2()”/>
</form>
<form action="/Action2" method=post>
<input type=submit name=sub2 onclick=”Fun1()”/>
</form>

Использование «ActionNameSelectorAttribute»: -

Это отличный и чистый вариант. «ActionNameSelectorAttribute» - это простой класс атрибутов, в котором мы можем написать логику принятия решения, которая будет определять, какое действие может быть выполнено.

Итак, первое, что нужно сделать в HTML, это указать имена кнопок для отправки на сервер.

Вы видите, что мы поместили «Сохранить» и «Удалить» в названия кнопок. Также вы можете заметить, что в действии мы просто указали имя контроллера «Клиент», а не конкретное имя действия. Мы ожидаем, что имя действия будет определяться «ActionNameSelectorAttribute».

<form action=”Customer” method=post>
<input type=submit value="Save" name="Save" /> <br />
<input type=submit value="Delete" name="Delete"/>
</form>

Поэтому, когда нажимается кнопка отправки, она сначала попадает в атрибут «ActionNameSelector», а затем, в зависимости от того, какая отправка запущена, вызывает соответствующее действие.

enter image description here

Итак, первым шагом является создание класса, который наследуется от класса «ActionNameSelectorAttribute». В этом классе мы создали простое свойство «Имя».

Нам также нужно переопределить функцию «IsValidName», которая возвращает true или flase. Эта функция - то, где мы пишем логику, должно ли действие быть выполнено или нет. Так что, если эта функция возвращает true, то действие выполняется или нет.

public class SubmitButtonSelector : ActionNameSelectorAttribute
    {
        public string Name { get; set; }
        public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)
        {
            // Try to find out if the name exists in the data sent from form
var value = controllerContext.Controller.ValueProvider.GetValue(Name);
            if (value != null)
            {
                return true;
            }
            return false;

        }
    }

Основное назначение вышеуказанной функции - в приведенном ниже коде. Коллекция «ValueProvider» содержит все данные, отправленные из формы. Поэтому он сначала ищет значение «Имя» и, если оно найдено в HTTP-запросе, возвращает значение «истина» или возвращает «ложь».

var value = controllerContext.Controller.ValueProvider.GetValue(Name);
if (value != null)
      {
        return true;
      }
      return false;

Этот класс атрибута затем может быть оформлен на соответствующее действие, и может быть предоставлено соответствующее значение «Имя». Поэтому, если отправка выполняет это действие и если имя соответствует названию кнопки отправки HTML, оно выполняет действие дальше или не выполняет.

public class CustomerController : Controller
{
        [SubmitButtonSelector(Name="Save")]
        public ActionResult Save()
        {
            return Content("Save Called");
        }
        [SubmitButtonSelector(Name = "Delete")]
        public ActionResult Delete()
        {
            return Content("Delete Called");
        }
}
7 голосов
/ 02 ноября 2010

Это техника, которую я бы использовал, и пока не вижу ее здесь. Ссылка (размещена Saajid Ismail ) это решение вдохновляет http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx). Оно адаптирует ответ Дилана Битти для выполнения локализации без проблем.

В представлении:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<button name="button" value="send"><%: Resources.Messages.Send %></button>
<button name="button" value="cancel"><%: Resources.Messages.Cancel %></button>
<% Html.EndForm(); %>

В контроллере:

public class MyController : Controller 
{
    public ActionResult MyAction(string button)
    {
         switch(button)
         {
             case "send":
                 this.DoSend();
                 break;
             case "cancel":
                 this.DoCancel();
                 break;
         }
    }
}
7 голосов
/ 26 июня 2009

Дэвид Финдли (David Findley) пишет о 3 различных вариантах для этого в своем блоге ASP.Net.

Прочтите статью Несколько кнопок в одной форме , чтобы увидеть его решения, а также преимущества и недостатки каждой из них. ИМХО, он предлагает очень элегантное решение, которое использует атрибуты, которыми вы украшаете свое действие.

7 голосов
/ 26 февраля 2012

Этот скрипт позволяет указать атрибут data-form-action, который будет работать как атрибут формирования HTML5 во всех браузерах (ненавязчиво):

$(document).on('click', '[type="submit"][data-form-action]', function(event) {
    var $this = $(this),
    var formAction = $this.attr('data-form-action'),
    $form = $($this.closest('form'));
    $form.attr('action', formAction);             
});

Форма, содержащая кнопку, будет размещена по URL-адресу, указанному в атрибуте data-form-action:

<button type="submit" data-form-action="different/url">Submit</button>   

Для этого требуется jQuery 1.7. Для предыдущих версий вы должны использовать live() вместо on().

6 голосов
/ 14 декабря 2012

У меня недостаточно представителей, чтобы комментировать в правильном месте, но я потратил на это целый день, поэтому хочу поделиться.

При попытке реализовать решение «MultipleButtonAttribute» ValueProvider.GetValue(keyValue) неверно вернется null.

Оказалось, что я ссылался на System.Web.MVC версии 3.0, когда она должна была быть 4.0 (другие сборки - 4.0). Я не знаю, почему мой проект не обновился правильно, и у меня не было других очевидных проблем.

Так что, если ваш ActionNameSelectorAttribute не работает ... проверьте это.

6 голосов
/ 19 февраля 2011

Вот метод расширения, который я написал для работы с несколькими кнопками изображений и / или текста.

Вот HTML-код для кнопки с изображением:

<input id="btnJoin" name="Join" src="/content/images/buttons/btnJoin.png" 
       type="image">

или для кнопки отправки текста:

<input type="submit" class="ui-button green" name="Submit_Join" value="Add to cart"  />
<input type="submit" class="ui-button red" name="Submit_Skip" value="Not today"  />

Вот метод расширения, который вы вызываете из контроллера с помощью form.GetSubmitButtonName(). Для кнопок изображения он ищет параметр формы с .x (который указывает на нажатие кнопки изображения) и извлекает имя. Для обычных кнопок input он ищет имя, начинающееся с Submit_, и извлекает команду впоследствии. Поскольку я абстрагируюсь от логики определения «команды», вы можете переключаться между кнопками «изображение + текст» на клиенте без изменения кода на стороне сервера.

public static class FormCollectionExtensions
{
    public static string GetSubmitButtonName(this FormCollection formCollection)
    {
        return GetSubmitButtonName(formCollection, true);
    }

    public static string GetSubmitButtonName(this FormCollection formCollection, bool throwOnError)
    {
        var imageButton = formCollection.Keys.OfType<string>().Where(x => x.EndsWith(".x")).SingleOrDefault();
        var textButton = formCollection.Keys.OfType<string>().Where(x => x.StartsWith("Submit_")).SingleOrDefault();

        if (textButton != null)
        {
            return textButton.Substring("Submit_".Length);
        }

        // we got something like AddToCart.x
        if (imageButton != null)
        {
            return imageButton.Substring(0, imageButton.Length - 2);
        }

        if (throwOnError)
        {
            throw new ApplicationException("No button found");
        }
        else
        {
            return null;
        }
    }
}

Примечание: Для текстовых кнопок необходимо добавить к имени префикс Submit_. Я предпочитаю этот способ, потому что это означает, что вы можете изменить значение текста (отображения) без необходимости изменения кода. В отличие от SELECT элементов, кнопка INPUT имеет только атрибут value и не имеет отдельного атрибута text. Мои кнопки говорят разные вещи в разных контекстах - но отображаются на одну и ту же «команду». Я предпочитаю извлекать имя таким образом, чем кодировать == "Add to cart".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...