Post-Redirect - Получить с ASP.NET - PullRequest
41 голосов
/ 21 марта 2011

Как реализовать шаблон 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 (потому что Redirect не существует).Правильно?
  • какое изменение кода должно произойти в файле aspx или aspx.cs для поддержки PRG?Предположительно, по крайней мере, код должен быть изменен на post где-то кроме MyPage.aspx.

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

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

См. также

Ответы [ 6 ]

36 голосов
/ 12 июня 2012

Обычно это можно сделать, создав веб-форму 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, когда вы публикуете форму, которая не читает состояние просмотра?

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

  • Что происходит с ViewState при перенаправлении на "настоящую" веб-форму aspx?

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

  • является ли ViewState несовместимым с ASP.net Post-Redirect-Get?

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

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

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

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

Response.Redirect (url).Это отправит ответ в браузер с указанием сделать новый запрос get.

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

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

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

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

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

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

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

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

7 голосов
/ 07 июня 2012

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

A) С PRG вы не POST на другую страницу, вы отправляете обратно на ту же страницу(см. диаграмму на странице википедии, на которую вы ссылаетесь.) Но ответ с этой страницы ДОЛЖЕН БЫТЬ ответом в 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) После того, как вы обработали нажатие кнопки, сохранили данные в БД (или в сеансе и т. Д.) И перед тем, как что-либо еще записать в поток ответа.

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

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

В) Если так, то почему?Если нет, то почему?

А) Это проще, вот почему.Отображение двух страниц: 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-адрес в качестве параметров строки запроса, чтобы установитьэти элементы управления на second_page.aspx.(Но вам может не потребоваться отображать на second_page.aspx что-либо похожее на first_page.aspx - поэтому здесь нет общего правила.)

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

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

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

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

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

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

5 голосов
/ 07 июня 2012

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

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

5 голосов
/ 07 июня 2012

Точно шаги Get Post Redirect:

image

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

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

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

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

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

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

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

4 голосов
/ 21 марта 2011

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

2 голосов
/ 12 июня 2012

Есть несколько вещей, которые входят в это.

  1. Установите атрибут action формы на главной странице (назовем его LaunchForm.aspx ) равным URL-адресу страницы "прокси" ( ProxyLaunchForm.aspx ).

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

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

  4. Затем (также в Page_Load ) выполните перенаправление (либо с помощью redirectUrl из # 2, либо просто с помощью URL-адреса ссылающейся страницы):

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

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

  5. В LaunchForm.aspx.cs , используйте в качестве базового класса подкласс Page , который переопределяет 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);
       }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...