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)
См. также
Ответы
Ответ 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);
}
}
}