Как наилучшим образом реализовать Сохранить | Сохранить и закрыть | Отменить действия формы в ASP.NET MVC 3 RC
Мне интересно, как вы можете реализовать несколько действий формы при отправке формы в asp.net mvc 3 RC.
Если я редактирую пользователя, например, я хотел бы иметь панель действий со следующими кнопками:
"Сохранить" | "Сохранить и закрыть" | "Отменить"
Сохранить. Отправляет форму и сохраняет ее, возвращая вас на экран редактирования. Может быть легко реализована как стандартная кнопка ввода/отправки. Здесь ничего особенного.
Код контроллера для этого может выглядеть как
public ActionResult Edit(UserViewModel model)
{
...
return RedirectToAction("Edit", model.Id");
}
Отмена - просто возвращает вас на предыдущий экран. Я думал об использовании тега привязки для этого.
<a href="@Request.UrlReferrer" class="button">Cancel</a>
Но я не понимаю, как реализовать "Сохранить и закрыть" , когда вам нужно отправить те же данные формы. Мне было интересно, может ли быть нулевым близким параметром?
public ActionResult Edit(UserViewModel model, bool? close)
{
...
return close.GetValueOrDefault(false) ? RedirectToAction("Index", model.Id" : RedirectToAction("Edit", model.Id");
}
Но как мне отправить этот дополнительный параметр вместе с формой в этом случае?
Если возможно, я хотел бы иметь одно действие формы для обработки отправки как в вышеупомянутом макете.
Мне также интересно, если кто-то еще придумал хорошую модель взаимодействия с пользователем вокруг этой идеи.
Решение
В итоге я использовал предложение Omar, но вместо того, чтобы передавать строку, я взял перечисление, поэтому мне не нужно выполнять строковые проверки во всех моих контроллерах.
public ActionResult Edit(UserViewModel model, FormAction actionType)
{
// pre-check
if (actionType == FormAction.Cancel)
// just return user to previous view and don't save.
// Save code
if (actionType == FormAction.Save)
return ...
else if (actionType == FormAction.SaveAndClose)
....
}
Поскольку мне нужен более дружественный текст "Сохранить и закрыть" на кнопке <input>
, но я хотел использовать перечисление, я внедрил собственный ModelBinder для FormAction, который провел синтаксический анализ.
Я не использовал тег <button>
, потому что теги уже были на месте для тегов <input>
.
Ответы
Ответ 1
У вас может быть несколько кнопок отправки в форме с тем же атрибутом name
, но с разными атрибутами value
. При нажатии любой кнопки кнопки value
будет отправлено на сервер.
Вы можете использовать простую ссылку для Cancel
, но я все равно включу ее как кнопку.
<input type="submit" name="actionType" value="Save" />
<input type="submit" name="actionType" value="Save and Close" />
<input type="submit" name="actionType" value="Cancel" />
И в вашем действии проверьте значения.
public ActionResult Edit(string actionType)
{
if(actionType == "Save")
{
// Save action
}
else if (actionType == "Save and Close")
{
// Save and quit action
}
else
{
// Cancel action
}
}
Если вам не нравится иметь длинный текст в атрибуте value
, вы можете использовать стандартный тег HTML <button>
, который позволяет вам определять отдельное значение и отдельный текст.
Ответ 2
Предложение от @Omar велико. Вот как я сделал это немного более общим в том случае, когда я хотел получить подтверждение, когда пользователю будет предложено удалить объект.
Заметка! в HttpPost я снова вынимаю объект, а не используя элемент, переданный методу. Вы можете уменьшить вызов БД, имея представление, содержащее все свойства, так что заполняется "Item".
Здесь модель просмотра
public class DeleteViewModel<T> {
public string ActionType { get; set; }
public T Item { get; set; }
}
контроллер
public ActionResult Delete(int id) {
DeleteViewModel<Category> model = new DeleteViewModel<Category>() {
Item = categoryRepository.Categories.FirstOrDefault(x => x.CategoryID == id)
};
return View(model);
}
[HttpPost]
public ActionResult Delete(DeleteViewModel<Category> model) {
if (model.ActionType == "Cancel")
return RedirectToAction("Index");
else if (model.ActionType == "Delete") {
var cat = categoryRepository.Categories.FirstOrDefault(x => x.CategoryID == model.Item.CategoryID);
categoryRepository.Delete(cat);
return RedirectToAction("Index");
}
//Unknown Action
return RedirectToAction("Index");
}
Просмотр
<div class="actions">
<div class="actions-left"><input type="submit" value="Cancel" name="ActionType"/></div>
<div class="actions-right"><input type="submit" value="Delete" name="ActionType" /></div>
</div>