Как обращаться с кнопкой редактирования и удаления в той же форме в ASP.NET MVC?

Рассмотрим следующую разметку:

<h2>Edit SAS Program</h2>
@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post))
    {
        <input type="submit" class="button" value="Delete" />
    }
    <input type="submit" class="button" value="Save Changes" />
}

Я хотел бы иметь кнопку Delete на том же представлении, что и Edit. Однако это не позволяет мне иметь вложенные формы. Каков подходящий способ справиться с этой ситуацией?

Я попытался использовать этот ответ Как обрабатывать вложенные формы в ASP.NET MVC, но теперь он не работает.

Ответ 1

Лучшим и простым способом было бы использовать две формы, но не вставлять их:

<h2>Edit SAS Program</h2>
@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    <input type="submit" class="button" value="Save Changes" />
}

@using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post))
{
    <input type="submit" class="button" value="Delete" />
}

Таким образом у вас есть:

  • Две отдельные формы
  • Нет запросов GET
  • Кнопка удаления под кнопкой редактирования, что имеет больше смысла, когда вы находитесь на виду, которое позволяет вам что-то редактировать.

Ответ 2

Я использовал бы разные значения для имени кнопки в той же форме:

@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    <button name="action" value="delete">Delete</button>
    <button name="action" value="save">Save Changes</button>
}

а затем включите контроллер:

[HttpPost]
public ActionResult Edit( SomeModel model, string action )
{
    switch( action ) {
        case "delete":
            // delete action
            break;
        case "save":
            // save action
            break;
    }
}

Код написан из памяти, но он работает в процессе производства. Обратите внимание, что кнопки имеют тип по умолчанию - submit.

Ответ 4

Во-первых, вы не можете вставить элемент <form>. Спецификация не позволяет этого. Поскольку вы используете шаблон MVC, у меня есть два варианта, которые пришли мне на ум:

  • Вы можете сохранить кнопку сохранения в качестве кнопки отправки формы и сделать кнопку удаления ссылкой HTML. Затем кнопка удаления будет нацелена на другой маршрут, это может быть примерно так: GET /program/delete/{id}.

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

Update

Существует третий вариант, более чистый: использование двух кнопок отправки с одинаковым атрибутом имени и разными значениями.

В вашей форме будут две кнопки:

public ActionResult MyAction(string submitButton) {
    switch (submitButton) {
        case "save":
            // ...
        case "delete":
            // ...
    }
}

Подробнее об этом отвечу: fooobar.com/questions/2722/...

Ответ 5

Вы также можете использовать функцию html 5 для таргетинга формы на кнопку ввода. Ниже я создал форму удаления и сохранения и кнопки отправки вне форм, но нацелил их на атрибут form.

Я думаю, что большинство браузеров поддерживают это, кроме IE.

Не требуется javascript.

@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post, new { id = "editForm" }))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)
}

@using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post, new { id = "deleteForm" }))
{
    <input type="submit" class="button" value="Delete" />
}

<input type="submit" class="button" value="Save" form="editForm"/>
<input type="submit" class="button" value="Delete" form="deleteForm" />

Это позволяет создать красивую макетную кнопку без каких-либо причудливых javascript или CSS-стилей.

Ответ 6

Изменить: здесь, как это сделать с помощью ajax с использованием HttpPost.

//
// POST: /Divisions/Delete
[HttpPost, ActionName("Delete"), Authorize]
public ActionResult DeleteConfirmed(int id)
{
    Division division = _db.Divisions.Single(x => x.DivisionId == id);

    string errorMessage;
    if (DbRelationEnforcer.CanDelete(_db, division, out errorMessage))
    {
        division.SetDeleted(User.Identity.Name);
        _db.SaveChanges();
        return Json(new JsonResponseCreatePartial { Success = true }, JsonRequestBehavior.AllowGet);
    }

    return Json(new JsonResponseCreatePartial { Success = false, Message = errorMessage }, JsonRequestBehavior.AllowGet);
}

Затем в представлении вы должны использовать <input type="submit">Save changes</input> для сохранения изменений (в форме) и простой ссылки/кнопки для удаления, например:

<h2>Edit SAS Program</h2>
@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    <input id='delete-btn' type="button" class="button" value="Delete" />
    <input type="submit" class="button" value="Save Changes" />
}

Наконец, вы должны использовать JS для публикации в своем действии из представления, когда пользователь нажимает кнопку "Удалить".

<script type='text/javascript'>
    $(function() {
        $("input#delete-btn").click(function(){
            $.post('@Url.Action("Delete")', '@Model.Id', function(data) {
                if(data.Success) {
                    ' ... handle the success case
                } else {
                    ' ... error management
                }
            });
        });
    });
</script>

Это будет работать, но для лучшего UX было бы предпочтительнее, чтобы кнопка "Удалить" отображалась в представлении "Index/list" и с помощью диалогового окна JQuery UI для подтверждения перед выполнением сообщения ajax. Это пропустит загрузку страницы "Редактировать", если/если вы хотите удалить несколько элементов один за другим.