Post-Redirect-получить с ASP.NET

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

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

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

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

enter image description here

решение проблемы После Перенаправления-Get узор.

что такое метод PRG может быть реализован в ASP.NET?


вопрос сосредотачивается вокруг проблемы:

  • как <asp:Button> выполнить POST в место, которое не является его первоначальной формой?
  • что станет с ViewState когда вы отправляете сообщение в форму, которая не читает состояние просмотра?
  • что станет с ViewState при перенаправлении на" реальный " aspx web форма?
  • is ViewState принципиально несовместимы с ASP.net Пост-Редирект-Получить?
  • is ASP.net принципиально несовместимый с После Перенаправления--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 in ASP.net?

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

см. также

6 ответов


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

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

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

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

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

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

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-адреса в перенаправлении(...). Он загрузит страницу,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)

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


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

A) с PRG вы не публикуете на другой странице, вы публикуете обратно на ту же страницу (см. диаграмму на странице Википедии, с которой вы связаны.) Но ответ с этой страницы должен быть ответом 30X (обычно 302.)

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

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

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) Ответ.Redirect ("new_page_you_are_redirecting_to.aspx") в методе bblaunch_click метода old_page_you_are_posting_from.аспн

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

A) см. выше

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

A) после обработки кнопки нажмите, сохраните данные в БД (или сеанс и т. д.), и прежде чем вы напишете что-либо еще в поток ответов.

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

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

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

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

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

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

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

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

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

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


точные шаги Post Redirect Get - это:

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

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

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

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

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

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

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

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


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

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


вызов ответ.Перенаправить метод для перехода в другое место.


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

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

  2. (опционально) добавить скрытый input с именем параметр redirecturl к форме и значению URL, который сообщает ProxyLaunchForm.аспн где перенаправить, как только он закончит выполнение запуска (R часть PRG).

  3. теперь о ProxyLaunchForm.аспн реализация должна происходить внутри в обработчик событий, потому что он имеет доступ к данным формы post. Запуск здесь.

  4. затем (также в в), перенаправление (либо с помощью параметр redirecturl из #2, или просто с помощью ссылки URL страницы):

    ответ.перенаправленный запрос.Params ["redirectUrl"]?? Запрос.UrlReferrer.AbsoluteUri);

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

  5. на LaunchForm.аспн.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);
       }
    }
}