Подтвердить что ты не робот

Как наилучшим образом реализовать Сохранить | Сохранить и закрыть | Отменить действия формы в 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>.

4b9b3361

Ответ 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>