Asp.net mvc3 бритва с несколькими кнопками отправки - PullRequest
32 голосов
/ 18 апреля 2011

Я использую MVC3 Razor. У меня есть 2 кнопки отправки, но проблема заключается в том, что обе кнопки отправки вызывают проверку модели. Я хочу подключить отдельные кнопки отправки с определенными элементами управления вводом для проверки.

Ответы [ 8 ]

64 голосов
/ 04 августа 2011

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

Просмотр:

 <input type="submit" id="EnterprisePush" name="btnSubmit" value="Push" />
 <input type="submit" id="EnterprisePull" name="btnSubmit" value="Pull" />

Контроллер:

[HttpPost]
public ActionResult EnterpriseAdmin(int id, string btnSubmit, FormCollection collection)
{
  switch (btnSubmit) {
    case "Push":
      /* Do Something here */
      break;
    case "Pull":
      /* Do Something else here */
      break;
  }
30 голосов
/ 19 апреля 2011

Браузер всегда будет отправлять всю форму независимо от того, какую кнопку отправки вы нажимаете.

Лучшим решением было бы иметь две кнопки отправки с одинаковым значением для атрибута name и разными значениями.для атрибутов value.

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

В вашей форме вы бы имели что-то вроде этого:

<button type="submit" name="Command" value="command1">Do Command #1</button>
<button type="submit" name="Command" value="command2">Do Command #2</button>

Ваша модель формы будет выглядеть так:

public class MyFormModel() {
    public string Command {get;set;}
    public string SomeOtherVal {get;set;}
}

Ваш контроллер \ действие будет выглядеть так:

public ActionResult HandleFormSubmit(MyFormModel model) {
    if (model.Command == "command1") {
        // do something
    } else if (model.Command == "command2") {
        // do something else
    }
}
21 голосов
/ 10 марта 2012

Во-первых, вы можете отключить проверку клиента на кнопке отмены, просто добавив в нее CSS-класс «отмена».См .: Отключение проверки на стороне клиента в MVC 3 кнопка «отмена» отправки

Во-вторых, также как и тестирование имени формы элемента отправки, как описано выше, вы можете использовать селектор настраиваемых действий.Вот мой, который я первоначально взял из сообщения в блоге, показанного в комментарии:

/// <summary>
/// Used to vary an action method based on which button in a form was pressed. This
/// is useful but is an anti-pattern because it couples the controller to names
/// used in the form elements. 
/// </summary>
/// <remarks>
/// See the example at http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx
/// </remarks>
public class AcceptButtonAttribute : ActionMethodSelectorAttribute
{
    public string ButtonName { get; set; }

    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
    {
        var req = controllerContext.RequestContext.HttpContext.Request;
        return !string.IsNullOrEmpty(req.Form[this.ButtonName]);
    }
}

В вашем контроллере:

    [HttpPost]
    [ActionName("Edit")]
    [AcceptButton(ButtonName = "Cancel")]
    public ActionResult Edit_Cancel(MyModel model)
    {
        return RedirectToAction("Index");
    }

    [HttpPost]
    [AcceptButton(ButtonName = "Save")]
    public ActionResult Edit(MyModel model)
    {
        // do real work here
    }

Обратите внимание, что вам нужно [ActionName ("Редактировать")], чтобы сообщить MVC, что, хотя используется другое имя метода, оно предназначено для действия Edit.

И в вашем представлении:

    <input type="submit" name="Save" value="Save" />
    <input type="submit" name="Cancel" value="Cancel" class="cancel" />
3 голосов
/ 11 июля 2011

Моим решением было сделать две вещи. Скажем, у нас есть кнопка Сохранить и еще одна кнопка Добавить что-то. Когда пользователь нажимает кнопку Сохранить, мы хотим, чтобы проверка клиента и проверка сервера выполнялись. Для более поздней кнопки мы не хотим никакой проверки.

  1. Временно отключить проверку клиента для второй кнопки (при нажатии):

Хорошо, что когда JavaScript отключен, проверка клиента в любом случае никогда бы не состоялась.

  1. Позаботьтесь о стороне сервера

Подобно тому, что говорит Брайан, когда вы нажимаете любую кнопку отправки в форме, публикуется вся форма и значение нажатой кнопки отправки. Вы можете определить, какая кнопка была нажата по названию. В приведенном выше примере, когда пользователь нажимает кнопку «Сохранить» и мы читаем Request.Form [«submit-button»] в действии контроллера, мы получаем «Сохранить». Если пользователь нажмет «Добавить что-то», мы получим «Добавить что-то». Именно так должен работать HTML.

Теперь, чтобы обойти магические строки повсюду, у меня обычно есть открытый статический класс в контроллере, например:

public class HomeController
{
    public static class Buttons
    {
        public const string Save = "Save";
        public const string AddSomething = "Add something";
    }
    // Action methods
}

Таким образом, вы можете использовать их для рендеринга формы:

&lt;input type="submit" name="submit-button" value="@HomeController.Buttons.Save" /&gt;

И вы можете легко прочитать нажатие кнопки в контроллере:

[HttpPost]
public ActionResult Index(Model viewModel)
{
    var buttonClicked = Request.Form["submit-button"];
    switch (buttonClicked) {
        case HomeController.Buttons.Save:
            return Save(viewModel);
        case HomeController.Buttons.AddSomething:
            return AddSOmething(viewModel);
    }
    return View();
}

В методе Save вы сначала спрашиваете, если ModelState.IsValid, и возвращаете модель представления, если нет, но в методе AddSomething мы устраняем любые ошибки:

public ActionResult AddSomething(Model viewModel)
{
    ModelState.Clear();
    // your code to add something to model
    return View(viewModel);
}

Это вы содержали все в чистоте, порядке и проверяемости. И вы можете ввести константу для атрибута html-имени кнопки submit. Можно также сделать все константы с T4MVC. Аналогичное решение применимо для случаев, когда вам нужно поле со списком «auto postback», за исключением того, что вам нужно скрытое поле, которое устанавливается с помощью события onchange элемента select.

Надеюсь, это поможет.

2 голосов
/ 18 мая 2012

Просто используйте этот код в качестве шаблона:

@{
    var nextButtonVal = "Next >>";
    var backButtonVal = "<< Back";
    if (IsPost) {
      if(Request["navigate"].Equals(backButtonVal)){Response.Redirect("~/pageFoo");}
      if(Request["navigate"].Equals(nextButtonVal)){Response.Redirect("~/pagebar");}
    }
}

<input type="submit" value="@backButtonVal" title="Back" name="navigate"/>
<input type="submit" value="@nextButtonVal" title="Next" name="navigate"/>
1 голос
/ 27 июля 2011

Последнее, что я хотел бы сделать, вместо использования интеллектуальных строк, используйте enum, чтобы определить значение для каждого входного тега. Использование синтаксиса бритвы:

@Enum.GetName(typeof(YourEnumType), yourEnum.WhateverValue)

тогда в вашем контроллере:

public ActionResult DoSomethingBasedOnEnumValue(string enumValue)
{
    YourEnumType localVar = (YourEnumType)Enum.Parse(typeof(YourEnumType), enumValue);

    switch(localVar)
    {
        case YourEnumType.Action1:
            //do something
            break;

        case YourEnumType.Action2:
            //do something else
            break;
    }
    return View();
}
0 голосов
/ 21 июня 2013

Имя кнопки «Отправить» не будет отображаться на стороне сервера, если во всей этой ситуации вы будете использовать атрибут [Remote] для свойства модели проверки.

0 голосов
/ 30 мая 2013

Если вы хотите выполнить отдельное действие для удаления, попробуйте это.

добавить действие удаления в контроллер и пометить его как HttpDelete,

[HttpDelete]
public ActionResult Edit(int id, string foo) {
   ...
}

И в представлении, имя кнопки должно быть X-HTTP-Method-Override, а значение должно быть DELETE

<button name="X-HTTP-Method-Override" value="DELETE" formnovalidate="formnovalidate" class="cancel">Delete</button>

примечание: все большинство браузеров не поддерживают другие методы HTTP, такие как HEAD, PUT или DELETE. но путем добавления заголовка к HTTP-запросу X-HTTP-Method-Override, который должен интерпретироваться службой и действовать независимо от используемого метода HTTP. Таким образом, приведенный выше код добавит заголовок к запросу, например X-HTTP-Method-Override: DELETE. и .net Framework сделает все остальное и предложит вам удалить действие.

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