Как отображать сообщения пользователю после перенаправления POST + HTTP

Я использую шаблон PRG, чтобы избежать отправки нескольких форм. Однако у него есть серьезный недостаток - вы не можете просто echo отправить пользователю подтверждающее сообщение (очевидно, что пользователь не увидит страницу, он будет перенаправлен на другую).

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

  • Используйте настраиваемый URL-адрес перенаправления, например: http://example.com/?msg=data-saved. У него нет гражданства, поэтому я считаю его вполне надежным. Но это создает проблемы, когда пользователь копирует ссылку, добавляет ее в закладки и т. Д.
  • Сохраните переменную сеанса / файл cookie и проверяйте ее при каждой загрузке страницы. Если он установлен, очистите его и отобразите сообщение. Вроде нормально, но я не уверен насчет этого - он сильно зависит от файлов cookie, это немного сложнее.

Или, может быть, есть другие способы, о которых я не знаю? Какая-то комбинация сессий и параметров URL? Я не знаю.

Какой, на ваш взгляд, лучший способ? У какого из них меньше всего недостатков? Каковы плюсы и минусы?


person Maciej Łebkowski    schedule 29.06.2009    source источник


Ответы (6)


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

Кроме того, обработка сеанса - одна из тех вещей, о которых обычно заботятся фреймворки веб-разработки.

person Eli    schedule 29.06.2009

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

Большинство удобных решений основаны на сеансах или имеют более серьезные недостатки (например, встраивание сообщения в строку запроса).

Если вы не можете гарантировать, что у вас будут сеансы, другой (довольно затратный) метод - перенаправление на разные представления в зависимости от результата отправки формы. Например, вы можете перенаправить на EditWidgetView, EditWidgetSaveSuccessfulView или EditWidgetSaveErrorView (или, возможно, вы просто не перенаправляете при ошибках). Для некоторых языков и фреймворков это непрактично до такой степени, что вы вообще отказываетесь от показа сообщений подтверждения / ошибок, но для других это может того стоить.

person Jeff Sternal    schedule 29.06.2009

Если вы не хотите полагаться на сеансы по какой-либо причине, вы можете использовать переменную Get / настраиваемый URL-адрес, а затем, если эта переменная присутствует, проверьте ссылку. Если ссылка правильная, отобразите сообщение. Да, это добавляет уверенности в отправке ссылок для отображения подтверждающего сообщения, но в остальном вы полагаетесь на сеансы (которые, хотя и надежны, но не на 100% идеальны для всех решений).

И, честно говоря, некоторые крупные сайты, которые обычно неплохо разбираются в подобных вещах, просто вставляют «actiondone = true» в URL-адрес. (Я заметил, что Facebook делает это в некоторых местах.)

person TheLordRedbeard    schedule 11.07.2009
comment
+1, потому что я тоже думал об использовании опции Referer [sic] ;-) - person Rafa; 21.01.2011

Это зависит от того, на какой платформе вы работаете.

Ruby on Rails вызывает это flash [: notice] = "Ваше действие было выполнено", ASP.NET MVC вызывает это TempData ["notice"] = "Ваше действие было выполнено" ...

В основном они просто хранят данные в HttpSession только для одного пути туда и обратно. Таким образом, вы можете получить данные по другому веб-запросу.

person Ben Scheirman    schedule 29.06.2009
comment
Другими словами, фреймворк часто принимает ваше второе предложение об использовании хранилища данных сеанса, связанного с файлом cookie. - person Eli; 29.06.2009

Очень поздно к этому обсуждению ..

Вы можете использовать комбинацию двух предложенных вариантов.

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

Client: GET  http://example.com/foo.cgi
Server: 200  Ok

Client: POST http://example.com/bar.cgi
Server: 303  http://example.com/foo.cgi?msg=true

Если аргумент msg равен true, сообщение будет просмотрено в сеансе и (если найдено) включено в ответ клиенту.
Если аргумент msg равен ! true (или отсутствует), этап поиска пропускается.

С помощью этого решения вы предотвращаете отображение фактического сообщения в URL-адресе, URL-адрес указывает только на то, что сообщение могло быть. Кроме того, сообщение отображается только при необходимости (= при обнаружении в сеансе).

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

person Jacco    schedule 11.03.2010
comment
Вы можете сделать это, проверив наличие сообщения в данных сеанса (и оно очищается после каждого запроса). Здесь нет необходимости в параметре _GET ... - person Maciej Łebkowski; 15.03.2010
comment
Вы могли бы, но тогда вы запрещаете своему браузеру когда-либо кэшировать ресурс - person Jacco; 15.03.2010

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

person chaos    schedule 29.06.2009