Метод POST, вызываемый в MVC UserControls и их родительских представлениях - PullRequest
3 голосов
/ 07 февраля 2009

Переписано: Мне показалось, что мой оригинальный пост был неправильно понят. С тех пор я сообщил об этом как об ошибке со следующим описанием. Мой оригинальный пост по этому вопросу можно найти ниже второго <HR>.


У меня есть серьезная проблема с POST в пользовательском элементе управления.

  • У меня есть UserControl, в котором есть контроллер, содержащий два метода ActionMetd, называемый ContactForm. Второй имеет ActionVerb.POST для ответа на постбэк. Пользовательский элемент управления в основном используется через AJAX - но на самом деле это не имеет значения. Очевидно, что эти методы действия создают частичное представление.

  • У меня есть главная страница, содержащая дополнительную HTML-форму для «EnterContest». Опять же - у его контроллера есть два ActionMethods, называемых EnterContest, один из которых отвечает на ActionVerb.POST. Это представление содержит «ContactForm» в боковой панели, которая отображается с:

    <% Html.RenderAction("ContactUsForm", "Company", new { commentsBoxHeader = "Questions" }); %>

Проблема возникает при отправке обратно формы «EnterContest» (основная форма в представлении).

Запрос POST от Fiddler содержит только эту строку запроса (очевидно, не содержащую каких-либо данных POST из формы обратной связи, поскольку это совершенно отдельное действие HTTP).

contestId = ND09 и электронная почта = Фред & btnEnterContest = Submit

(да, это похоже на GET, но это что показывает Fiddler для POST тоже)

  • Первый - (как и ожидалось) - в главном контроллере вызывается метод EnterContest (данные FormCollection). Это обрабатывает отправку формы для участия в конкурсе - звонит в веб-службу и т. Д.

  • Второе - (НЕ ожидается) - вызывается метод POST контроллера «ContactForm». Это сразу дает сбой, потому что в нем отсутствуют ожидаемые параметры - и мы не хотим, чтобы он вызывался в любом случае. Это происходит во время того же запроса Http.

Если я взгляну на трассировку стека - она ​​вызывается со страницы динамически сгенерированного aspx, происходящей из строки кода Html.RenderAction, показанной выше. Очевидно, что происходит то, что код, который пытается частично визуализировать метод действия «ContactUs», просматривает запрос и видит, что есть метод для обработки POST, поэтому он направляет его туда, что ОЧЕНЬ ПЛОХО. Вероятно, где-то вокруг этого метода в рамках:

System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod

Это поведение ОЧЕНЬ сбивает с толку и действительно нарушает то, что казалось простой страницей. Я уверен, что это ошибка - потому что я не могу увидеть элегантную работу без некоторой действительно неуклюжей проверки в моем контроллере. Я думаю, что RenderAction находится в будущем, но я не знаю, присутствует ли проблема там или в основной структуре.

Просто чтобы прояснить, что НЕ происходит:

  • любой умный jQuery
  • более одного HTTP-запроса (проверено в Fiddler)
  • вложенные формы

Спасибо


Оригинальный пост

Я использую расширение RenderAction Html в ASP.NET MVC.

Я столкнулся с чем-то неожиданным, но в этом есть смысл, когда я думаю об этом.

Допустим, у меня есть представление, содержащее метод RenderAction для генерации контакта для части страницы.

<% Html.RenderAction("ContactUsForm", "Company", 
   new { commentsBoxHeader = "Questions" }); %>

В этом случае частичное представление, которое оно генерирует, создает форму ajax, которая отправляет обратно через <%= Html.BeginAjaxForm() %>.

Так что, конечно, мне нужен результат действия для обработки обратной передачи AJAX.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ContactUsForm(FormCollection formdata)

Теперь проблема возникает, когда родительское представление , содержащее это частичное действие рендеринга, имеет нормальную (не-ajax) форму с действием POST. В результате метод POST для действия ContactUsForm вызывается в дополнение к действию POST для основного представления. Внутри этого действия свойство formdata содержит все свойства родительского представления, поэтому ContactUsForm умирает с нулевой ссылкой или чем-то в этом роде.

Я предложил 3 возможных решения:

1) создать другое имя действия для обратной записи для любых пользовательских элементов управления на странице. Это имеет недостаток, заключающийся в том, что вы должны отправлять обратно в другую функцию, чем при создании частичного представления. Часто это может быть более громоздким, но я сейчас и делаю.

2) отметьте каждый метод POST (вы должны помнить, чтобы выполнить эту проверку в методе действия каждого пользовательского элемента управления POST), чтобы увидеть, предназначены ли данные формы для этой формы, и если нет, вернуть представление по умолчанию.

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResultContactUsForm(FormCollection formData)
    {
        if (formData["btnSubmitContactUsForm"] == null) {

            // "This form is not for us!";
            // figure out how (if is possible) to return the get default view here
            // and call it with the right arguments
        }
    } 

3) сообщить об ошибке.

Что мне здесь делать? Я склонен думать об этом как об ошибке

Редактировать: Одна очень важная вещь, которую я должен подчеркнуть, это то, что оба метода POST вызываются - так что это не просто нечто вроде вложенной формы.

Редактировать 2: В Fiddler я вижу только один запрос. Проблема в том, что, когда он пытается отобразить ContactUsForm после того, как уже обработал POST для моей главной страницы, он обращается к методу POST для ContactUsForm вместо не-пост-обработчика.

Ответы [ 2 ]

3 голосов
/ 07 февраля 2009

EDIT2 : я только что заметил, что вы используете RenderAction вместо RenderPartial. Я подозреваю, что происходит то, что он использует RequestContext размещенной формы, чтобы выбрать, какой метод ContactUsForm выбрать при вызове RenderAction. Возможно, это правильное поведение, поскольку действие вызывается из постбэка, а не того, которое вы намеревались. Я бы подошел к этому совершенно по-другому. Создайте частичное с помощью ViewUserControl и включите его на страницу, используя вместо этого RenderPartial. Удалите метод GET ContactUsForm и используйте только версию POST. То есть сама форма генерируется как ViewUserControl с разметкой, предопределенной или динамически генерируемой с помощью параметров, передаваемых через ViewData. Ответ формы обрабатывается через действие контроллера.

РЕДАКТИРОВАТЬ : Поскольку вы указываете, что вложение не является проблемой, возможно, что вы используете javascript (скажем, jQuery) для запуска отправки, и ваш селектор слишком широк. Если, например, у вас есть код, подобный следующему, который будет учитывать поведение, которое вы видите.

$(document).ready( function() {
    $('#mybutton').click( function() {
       $('form').submit();
    });
});

Оригинальный ответ: (оставлено для контекста)

Похоже, у вас есть вложенные формы в вашем представлении. Попробуйте переместить RenderAction за пределы формы в родительском представлении и посмотрите, решит ли это вашу проблему. Мне кажется, что формы в представлениях MVC должны быть компактными и охватывать только разметку, содержащую фактические входные данные. Это изменение веб-форм, когда вы обычно заключаете в форму всю свою пометку. Используйте CSS для управления макетом, если вам нужно, чтобы элементы формы выглядели смешанными.

1 голос
/ 23 апреля 2010

Это фактически подтвержденная ошибка как в ASP.NET MVC 1.0 с библиотекой MVC Features, так и в ASP.NET MVC 2.0. RenderAction работает неправильно, когда запрос POST. Я отправил сообщение об ошибке в ASP.NET Issue Tracker на Codeplex, пожалуйста, проголосуйте за него :) http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=5847

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...