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

Post-Redirect-Получить с помощью ASP.NET

Как я могу реализовать шаблон Post-Redirect-Get с ASP.NET?

Щелчок на кнопке выполняет некоторую обработку:

<asp:Button id="bbLaunch" OnCommand="bbLaunch_Click" />

Пользователь нажимает кнопку, запускается космический корабль, повторное использование веб-страницы. Если пользователь нажимает F5, они получают предупреждение:

enter image description here

Решение проблемы - это шаблон Post-Redirect-Get.

Каков метод, с помощью которого PRG может быть реализован в ASP.NET?


Вопрос о проблемах:

  • как <asp:Button> выполнить POST место, которое не является его первоначальной формой?
  • Что будет с ViewState при отправке в форму, которая не считывает состояние просмотра?
  • Что происходит с ViewState при перенаправлении на "реальную" веб-форму aspx?
  • ViewState принципиально несовместим с ASP.net Post-Redirect-Get?
  • является ASP.NET принципиально несовместимым с Post-Redirect - Get?
  • как (например, какой код) вы перенаправляетесь на "реальную" веб-форму aspx?
  • как (т.е. какой URL) вы перенаправляетесь на "реальную" веб-форму aspx? В вопросе о соотношении упоминается Response.Redirect(Request.RawUrl);
  • когда (т.е. в каком обработчике событий) вы перенаправляетесь на "реальную" веб-форму aspx?
  • связанные вопросы поднимают вопросы о том, как вы публикуете данные формы. Подразумевается, что HTML-формы не могут использоваться - и все данные формы должны быть добавлены в строку запроса. Это правда? Если да, то почему? Если нет, почему бы и нет? Может ли отображать данные формы в строке запроса?
  • В связанном вопросе упоминается Server.Transfer. Использование Server.Transfer полностью неверно и никоим образом не решает проблему Post-Redirect-Get (потому что нет перенаправления). Правильно?
  • какое изменение кода должно произойти в файле aspx или aspx.cs для поддержки PRG? Предположительно, по крайней мере, код должен быть заменен на POST где-то, кроме MyPage.aspx.

Другими словами: Как вы выполняете Post-Redirect-Get в ASP.net?

Примечание: ASP.net(т.е. не ASP.net MVC)

См. также

4b9b3361

Ответ 1

Обычно вы делаете это, создавая веб-форму aspx, которая использует запрос, чтобы сигнализировать, какую запись загружать/обрабатывать.

Скажем, у вас есть страница, которая позволяет вам обновлять информацию о клиенте:

http://www.mysite.com/customer.aspx

Вы загрузили форму с помощью идентификатора в запросе:

http://www.mysite.com/customer.aspx?CustomerId=42

В коде кода у вас будет что-то вроде этого:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        int customerId = 0;
        if (!string.IsNullOrEmpty(Request.QueryString["CustomerId"]))
        {
            int.TryParse(Request.QueryString["CustomerId"], out customerId );
        }
        if (customerId == 0) 
        {
            //handle case when no valid customer id was passed in the qs here
        }
        else 
        {
            //load customer details, bind controls etc
            //make sure to handle the case when no customer was found using the id in the qs
        }
    }
}

Тогда где-то на вашей странице у вас будет кнопка, которая сохранит изменения. Эта кнопка будет иметь обработчик OnClick в коде позади:

protected void SaveClicked(object sender, EventArgs e)
{
    //save changes to database here

    //Redirect if all went well
    Response.Redirect("http://www.mysite.com/customer.aspx?CustomerId=" 
        + idOfSavedCustomer.ToString());
}

Это должно быть в основном. Переадресация заставит браузер выдать новый запрос GET для URL-адреса в Redirect (...). Он загрузит страницу, if (!IsPostBack) запустится и инициализирует страницу новыми значениями, которые вы только что сохранили в предыдущем сообщении.

Для всего этого трафик между браузером и сервером будет выглядеть примерно так:

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send back some html)

Browser: POST http://www.mysite.com/customer.aspx?CustomerId=42 (post data sent in request)
Server: 302 (point to http://www.mysite.com/customer.aspx?CustomerId=42)

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send html)

На среднем шаге сервер в основном говорит:

"Этот запрос на почту, который вы мне прислали, я закончил с этим. Теперь, пожалуйста, на эту другую страницу здесь..."

Тот факт, что URL-адрес действительно ссылается на одну и ту же страницу, не важен.


Некоторые размышления в ответ на ваш список вопросов:

  • как выполнить POST в место, которое не является оригинальная форма?

Вы можете сделать это, установив атрибут action в форме или вы можете установить PostBackUrl на кнопку.

  • что будет с ViewState при отправке в форму, которая не read view state?

Зависит. Если вы просто разместите форму на другой странице, вы можете использовать директиву <% @PreviousPageType.../ " > , чтобы сообщить" новую "страницу, на которой появилась почта. Это будет просто работать с опубликованными данными на новой странице. Подробнее см. .

  • что будет с ViewState при перенаправлении на "реальный" aspx веб-форма?

Состояние просмотра отправляется в почтовом запросе. При переадресации браузер загрузит новую страницу и создаст ее собственный viestate.

  • - ViewState принципиально несовместим с ASP.net Post-Redirect-Get?

Зависит от того, как вы на это смотрите. После перенаправления новая страница не будет иметь доступ к представлению страницы страницы раньше.

  • ASP.net принципиально несовместим с Post-Redirect - Get?

Нет. См. Пример выше.

  • как (например, какой код) вы перенаправляетесь на "реальную" веб-форму aspx?

Response.Redirect(URL). Это отправит ответ в браузер, сообщая ему сделать новый запрос на получение.

  • когда (т.е. в каком обработчике событий) вы перенаправляетесь на "реальный" aspx веб-форма?

Когда вы выполнили всю работу, необходимую для обработки почтового запроса.

  • связанные вопросы поднимают вопросы о том, как вы публикуете данные формы. Там подразумевается, что HTML-формы не могут использоваться - и все данные формы должен быть добавлен в строку запроса. Это правда? Если да, то почему? Если не, почему нет? Может ли браузер ввести данные формы в строку запроса?

Перенаправление почтового запроса плохо поддерживается, и его, вероятно, следует избегать. Это можно сделать (с некоторым браузером), используя HTTP-ответ 307. При этом сервер эффективно сообщает браузеру, что "я не буду обрабатывать ваш почтовый запрос, отправьте его на эту другую страницу".

  • В связанном вопросе упоминается Server.Transfer. Использование Server.Transfer - полностью неправильный и никоим образом не решает проблему Post-Redirect-Get (потому что нет перенаправления). Правильно?

Server.Transfer(...) - это то, что происходит на стороне сервера. Браузер не знает об этом. В основном страница может использовать Server.Transfer, чтобы некоторая другая страница выполняла некоторую обработку, и эта страница будет отвечать за отправку ответа обратно в браузер. Но браузер подумает, что это была исходная страница.

  • какое изменение кода должно произойти в файле aspx или aspx.cs для поддержки PRG? Предположительно, по крайней мере, код должен быть изменен для публикации где-то помимо MyPage.aspx.

Нет, можно использовать обычный пост. Фокус в том, чтобы иметь один (или несколько) конкретных обработчиков событий на странице, которая выполняет Repsonse.Redirect после обработки опубликованных данных.

Ответ 2

Q), как выполнить POST в месте, которое не является его первоначальной формой?

A) С PRG вы не отправляете POST на другую страницу, вы отправляете ее обратно на ту же страницу (см. диаграмму на странице wikipedia, с которой вы связались.) Но ответ с этой страницы ДОЛЖЕН БЫТЬ 30-кратным ответом ( обычно 302.)

Q) Что будет с ViewState при отправке в форму, которая не считывает состояние просмотра?

A) Состояние представления есть, когда вы выполняете POST, но там нет состояния просмотра для новой страницы, на которую вы выполняете GET.

Q) что будет с ViewState при перенаправлении на "реальную" веб-форму aspx?

A) Наверху больше нет состояния просмотра, перенаправляемого на страницу.

Q) является ViewState принципиально несовместимым с ASP.net?

A) ViewState не является несовместимым с ASP.NET. Это (в основном) бесполезно для P/R/G для отображения страницы, на которую вы перенаправлены.

Q) является ASP.net принципиально несовместимым с Post-Redirect - Get?

A) Нет - но вы не можете чрезмерно полагаться на использование одной страницы и сохранять все свое состояние в viewstate, как указано выше. Тем не менее, ASP.MVC намного лучше отображает P/R/G

Q), как (например, какой код) вы перенаправляете на "реальную" веб-форму aspx?

A) Response.Redirect( "new_page_you_are_redirecting_to.aspx" ) в методе bbLaunch_Click old_page_you_are_posting_from.aspx

Q), как (т.е. какой url) вы перенаправляетесь на "реальную" веб-форму aspx? В вопросе отношения упоминается Response.Redirect(Request.RawUrl);

A) См. выше

Q), когда (т.е. в каком обработчике событий) вы перенаправляетесь на "реальную" веб-форму aspx?

A) После того, как вы обработали кнопку, нажмите, сохраните данные в DB (или сеансе и т.д.) и до того, как вы напишете что-нибудь еще в потоке Response.

Q) связанные вопросы поднимают вопросы о том, как вы публикуете данные формы. Подразумевается, что HTML-формы не могут использоваться - и все данные формы должны быть добавлены в строку запроса. Это правда?

A) Нет - нажатие кнопки в ASP.NET WebForms вернет POST на страницу.

Q) Если да, то почему? Если нет, почему бы и нет?

A) Это проще, поэтому нет. Отображение двух страниц: first_page.asp и second_page.aspx. У First_page.aspx есть кнопка на нем (вместе с другими веб-элементами ASP.NET, такими как текстовые поля и т.д., Которые пользователь заполнил.) Когда они нажимают кнопку, POST создается в first_page.aspx. После обработки данных (которые, скорее всего, внутри viewstate, хотя это абстрагируется), вы перенаправляете пользователя на second_page.aspx с помощью Response.redirect. Second_page.aspx может отображать то, что вы хотите. Если вы хотите (или нужно) отображать пользовательский интерфейс, похожий на то, что было на first_page.aspx, включая элементы управления и то, что они ввели, вы хотели бы сохранить это в сеансе, cookie, URL как параметры querystring, чтобы установить эти элементы управления на second_page.aspx. (Но вам может не понадобиться отображать что-либо на second_page.aspx, что похоже на first_page.aspx, поэтому здесь нет общего правила.)

Q) Может ли браузер помещать данные формы в строку запроса?

A) Да, если вы установите метод GET вместо POST. Вы не можете переопределить WebForms для этого, и это не требуется для PRG

Q) связанный с этим вопрос упоминает Server.Transfer. Использование Server.Transfer совершенно неверно и никоим образом не решает проблему Post-Redirect-Get (потому что нет перенаправления). Правильно?

A) По существу

Q), какое изменение кода должно произойти в файле aspx или aspx.cs для поддержки PRG? Предположительно, по крайней мере, код должен быть изменен для публикации где-то помимо MyPage.aspx.

A) Код все равно должен быть отправлен назад (как упоминалось выше). Но тогда Mypage.aspx должен перенаправить на новую страницу в обработчике кнопок.

Ответ 3

Точные шаги Post Redirect Get следующие:

http://www.planethost.gr/PostRedirectGet.jpg

У вас есть форма, в которой вы заполняете данные, и после вашего действительного отправки (POST) вы вставляете их в свою базу данных и даете им идентификатор подтверждения, затем вы перенаправляете пользователя на страницу с этим идентификатором подтверждения в качестве параметра URL, который используется как (GET). После перенаправления каждый F5-обновление считывает только данные и не вставляет их снова.

Код для вставки отличается от кода, который показывает подтверждение, вы даже можете сделать их разными страницами - вы можете сделать одну и ту же страницу с текстовыми полями только для чтения.

Переадресация простая функция Responce.Redirect asp.net

После POST и создания перенаправления единственное, что связывает вас с предыдущим действием, - это код подтверждения (а не viewstate).

Минус этого метода заключается в том, что на самом деле не распознается обновление, просто сделайте дополнительный шаг, который заставляет обновление не вставлять снова те же данные, - но для получения данных Get требуется дополнительный код.

Альтернативой является распознавание обновления и не перенаправление. Узнав обновление в ответном сообщении, вы можете избежать вставки одних и тех же данных с одним сообщением пользователю. Для этого есть несколько примеров в Интернете, и я успешно реализую их.

Один пример: http://www.codeproject.com/Tips/319955/How-to-prevent-Re-Post-action-caused-by-pressing-b

Ответ 4

Шаблон Post-Redirect-Get можно использовать в веб-формах. Я показал, как это можно сделать, конвертируя приложение MVC NerdDinner в Web Forms, http://navigationnerddinner.codeplex.com/. Я сохранил данные навигации точно так же, поэтому есть много примеров шаблона PRG.

Однако есть еще один способ избежать проблемы с F5/Refresh. Если вы обернете свою страницу в UpdatePanel (часть ASP.NET Ajax), все обратные копии будут преобразованы в частичные запросы страниц. Это означает, что когда F5 нажат, он обновит только исходный запрос GET (так как не было никаких последующих POST), и поэтому вы не получите предупреждение. (Примечание. Если JavaScript отключен, предупреждение все равно появится).

Ответ 5

Вы можете вызвать метод Response.Redirect, чтобы перейти в другое место.

Ответ 6

В этом есть несколько вещей.

  • Задайте атрибут действия формы на главной странице (позвоните на LaunchForm.aspx), равный URL-адресу страницы "proxy" (ProxyLaunchForm.aspx).

    < form id = "form1" runat = "server" action = "ProxyLaunchForm.aspx" method = "POST" >

  • (необязательно) Добавьте скрытый ввод с именем redirectUrl в форму и укажите URL-адрес, который сообщает ProxyLaunchForm.aspx, где нужно перенаправить после завершения запуска (часть R PRG).

  • Теперь в ProxyLaunchForm.aspx реализация должна выполняться внутри обработчика событий Page_Load, поскольку у этого есть доступ к данным формы. Выполните здесь запуск.

  • Впоследствии (также в Page_Load) выполните перенаправление (либо используя redirectUrl из # 2, либо просто используя URL-адрес ссылки):

    Response.Redirect(Request.Params [ "redirectUrl" ]?? Request.UrlReferrer.AbsoluteUri);

    По-прежнему существует вопрос о состоянии просмотра. Я думаю, что самый простой способ справиться с этим - изменить то, как состояние представления сохраняется. Как правило, он сохраняется в скрытом элементе ввода на странице и извлекается при обратной передаче (что, конечно же, означает, что он будет потерян после перенаправления из-за отсутствия состояния HTTP-состояния). Однако вы можете переопределить методы, которые использует ASP.net, и использовать его вместо этого (таким образом, он все равно будет присутствовать даже после действия прокси-сервера PRG). Итак, наконец...

  • В LaunchForm.aspx.cs используйте в качестве базового класса подклассу Страница, которая переопределяет методы SavePageStateToPersistenceMedium и LoadPageStateFromPersistenceMedium для хранения/извлечения их из сеанса, а не из скрытого поля формы. См. Ниже (и здесь больше информации о том, как это работает.).

*

public class PersistViewStateToSession : Page
{
    protected override void SavePageStateToPersistenceMedium(object viewState)
    {
        // serialize the view state into a base-64 encoded string
        LosFormatter los = new LosFormatter();
        StringWriter writer = new StringWriter();
        los.Serialize(writer, viewState);
        // save the string to session
        Session["LaunchViewState"] = writer.ToString();
    }

    protected override object LoadPageStateFromPersistenceMedium()
    {
       if (!Session["LaunchViewState"] == null)
           return null;
       else
       {
          string sessionString = (string)Session["LaunchViewState"];
          // deserialize the string
          LosFormatter los = new LosFormatter();
          return los.Deserialize(viewStateString);
       }
    }
}