Частичный вид — избегание вложенных форм

Просмотреть

@using (Html.BeginForm())
{
    ...form elements
    @Html.Action("PartialView")
}

Частичный просмотр

if (something) {
    <input type="submit" value="Submit" />
} else {
    @using (Html.BeginForm())
    {
        <input type="submit" value="Submit" />
    }

Может ли кто-нибудь предложить способ решения вышеуказанной проблемы?

Если оператор PartialView if возвращает false, я получаю вложенные формы. Я могу переместить закрывающую скобку формы в частичном представлении, чтобы избежать вложения форм, и страница отображается правильно, но это расстраивает визуальную студию, поскольку она ожидает увидеть закрывающую скобку в представлении. Это имеет значение?

Редактировать:

Основываясь на комментариях Криса, является ли приведенная ниже модификация лучшим подходом? то есть одна форма с двумя кнопками отправки, которые вызывают разный код в одном и том же методе действия?

Частичный просмотр

if (something) {
    <input type="submit" name="btn" value="Submit1" />
} else {
    <input type="submit" name="btn" value="Submit2" />
}

Контроллер

[HttpPost]
public ActionResult Index()
{
    if (btn == "Submit1") {
        ...do a thing
    } else {
        ...do another thing
    };
}

person user1405195    schedule 21.10.2013    source источник
comment
Пожалуйста dont use <form> inside another <form>   -  person Murali Murugesan    schedule 21.10.2013
comment
Спасибо Мурали. Это проблема. Какое решение?   -  person user1405195    schedule 21.10.2013
comment
Не можете ли вы спроектировать частичное представление таким образом, чтобы у него не было собственного Html.BeginForm?   -  person Chris Pratt    schedule 21.10.2013
comment
Может быть, мне придется сделать это, Крис. На данный момент каждая форма вызывает свой метод действия. Возможно, они оба должны вызывать один и тот же метод действия, содержащий оператор if, который возвращает true или false в зависимости от того, какая форма сделала вызов.   -  person user1405195    schedule 21.10.2013
comment
Я бы сказал, что это был бы лучший подход. В веб-формах подчиненные формы всегда представляют собой проблему, поскольку вся страница представляет собой форму. В результате очень типично просто называть кнопки отправки для каждой формы. На самом деле это не отдельные формы, но, дав кнопке отправки уникальное имя, вы можете проверить ее существование в данных публикации на стороне сервера и определить, какая форма была отправлена ​​пользователем.   -  person Chris Pratt    schedule 21.10.2013
comment
Я бы посоветовал вам использовать вызов ajax для отправки дочерней формы в другое действие.   -  person Sravan    schedule 23.10.2013
comment
Я не уверен, что люди понимают проблему. Каждый PartialView необходим OP, чтобы иметь форму, если только мы уже не находимся внутри нее. Вот в чем проблема. Нужен индивидуальный помощник.   -  person Odys    schedule 08.10.2014
comment
Можете ли вы описать всю проблему, так как может существовать лучшее решение. Пожалуйста, приведите пример «чего-то» в условии частичного просмотра.   -  person Tomaz Tekavec    schedule 09.10.2014


Ответы (2)


Тег <form> внутри другого тега <form> не является допустимым HTML

См. W3c Spec

Доступный обходной путь

http://blog.avirtualhome.com/how-to-create-nested-forms/

person Murali Murugesan    schedule 21.10.2013
comment
Я не уверен, что вы поняли проблему. - person Odys; 08.10.2014

Я столкнулся с той же проблемой и придумал помощника, который действительно решает ее.

/**
 * Ensure consequent calls to Html.BeginForm are ignored. This is particularly useful
 * on reusable nested components where both a parent and a child begin a form.
 * When nested, the child form shouldn't be printed.
 */
public static class SingleFormExtensions
{
    public static IDisposable BeginSingleForm(this HtmlHelper html)
    {
        return new SingleForm(html);
    }

    public class SingleForm: IDisposable
    {
        // The form, if it was needed
        private MvcForm _form;

        public SingleForm(HtmlHelper html)
        {
            // single per http request
            if (!HttpContext.Current.Items.Contains(typeof(SingleForm).FullName))
            {
                _form = html.BeginForm();
                HttpContext.Current.Items[typeof(SingleForm).FullName] = true; // we need the key added, value is a dummy
            }
        }

        public void Dispose()
        {
            // close the form if it was opened
            if (_form != null)
            {
                _form.EndForm();
                HttpContext.Current.Items.Remove(typeof(SingleForm).FullName);
            }
        }
    }
}

Чтобы использовать его, включите пространство имен расширения и выполните @Html.BeginSingleForm( везде, где хотите. Не только внутри вложенных представлений, но и в родителях.

Достопримечательности: Необходимо сохранить, была ли форма открыта ранее. У нас не может быть статической или статической переменной для каждого потока ThreadStatic, так как это может использоваться многими потоками Asp.Net. Единственным однопоточным местом для добавления переменной для каждого HTTP-запроса является словарь HttpContext.Current.Items.

Количество кнопок отправки не ограничено. Проблема заключается во вложенных элементах form. Чтобы избежать нескольких кнопок отправки, вы можете либо скрыть их с помощью jquery, либо расширить этот помощник, чтобы он автоматически добавлял кнопку отправки в конце.

person Odys    schedule 09.10.2014