Я использую MVC3 Razor. У меня есть 2 кнопки отправки кнопок на мой взгляд, но проблема, с которой я сталкиваюсь, заключается в том, что обе кнопки отправки заставляют валидацию модели. Я хочу подключить отдельные кнопки отправки с определенными элементами управления вводом для проверки.
Битва Asp.net mvc3 с несколькими кнопками отправки
Ответ 1
Я знаю, что это несколько месяцев назад, но решения здесь казались излишне сложными, и пока не принято ответа. Если вы назовете свои входы одинаковыми, но принесите им разные значения, вы можете получить это значение в своем контроллере, просто включив строку с именем ввода в качестве переменной. Вот как я решил эту проблему:
Вид:
<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;
}
Ответ 2
Браузер всегда будет отправлять всю форму независимо от того, какую кнопку отправки вы нажимаете.
Лучшим решением было бы иметь две кнопки отправки с тем же значением для атрибута 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
}
}
Ответ 3
Во-первых, вы можете отключить проверку клиента на кнопке отмены, просто добавив к нему класс CSS "cancel". См.: Отключить проверку на стороне клиента в 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, что, хотя и использует другое имя метода, оно предназначено для действия "Редактировать".
И в вашем представлении:
<input type="submit" name="Save" value="Save" />
<input type="submit" name="Cancel" value="Cancel" class="cancel" />
Ответ 4
Мое решение состояло в том, чтобы сделать две вещи. Скажем, у нас есть кнопка "Сохранить" и еще одна кнопка "Добавить что-то". Когда пользователь нажимает кнопку "Сохранить" , мы хотим, чтобы проверка клиента и проверка сервера выполнялись. Для более поздней кнопки мы не хотим, чтобы какая-либо проверка имела место.
- Временно отключить проверку клиента для второй кнопки (по щелчку):
< input type="submit" name= "submit-button" value = "Сохранить" / >
< input type="submit" name= "submit-button" value = "Добавить что-то" onclick = "document.forms [0].noValidate = true; document.forms [0].submit();" / >
Хорошо, что когда JavaScript отключен, проверка клиента никогда не состоялась бы.
- Позаботьтесь о стороне сервера
Подобно тому, что говорит Брайан, когда вы нажимаете кнопку отправки в форме, публикуется вся форма и значение кнопки отправки нажатой кнопки. Вы можете отличить, какая кнопка нажата по имени. В приведенном выше примере, когда пользователь нажимает кнопку "Сохранить" , и мы читаем 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
}
Поэтому вы можете использовать их для формы рендеринга:
<input type="submit" name="submit-button" value="@HomeController.Buttons.Save" />
И вы можете легко прочитать кнопку, нажатую в контроллере:
[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();
}
В "Сохранить метод" вы сначала спросите, если ModelState.IsValid и модель представления возврата, если нет, но в методе AddSomething мы устраним любые ошибки:
public ActionResult AddSomething(Model viewModel)
{
ModelState.Clear();
// your code to add something to model
return View(viewModel);
}
Это вы сохранили все чистое, аккуратное и проверяемое. И вы можете ввести константу для атрибута имени html для кнопки отправки. Возможно, также можно будет использовать все константы с T4MVC. Аналогичное решение относится к тому, когда вам нужен комбо-поле "auto postback", за исключением того, что вам нужно скрытое поле, которое устанавливается через событие onchange элемента select.
Надеюсь, что это поможет.
Ответ 5
Просто используйте этот код в качестве шаблона:
@{
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"/>
Ответ 6
Последнее, что я хотел бы сделать, это вместо использования интеллектуальных строк использовать 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();
}
Ответ 7
Если вы хотите иметь отдельное действие для удаления, попробуйте это.
добавьте действие удаления в контроллер и отметьте его как 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 сделает все остальное и направит вас на удаление.
Ответ 8
Введите имя кнопки не на стороне сервера, если во всей этой ситуации вы будете использовать атрибут [Remote] для свойства модели проверки.