ASP.NET MVC - TempData - Хорошая или плохая практика

96

Я использую AcceptVerbsметод, подробно описанный в сообщении блога Скотта Гу Preview 5, для работы с записями формы в ASP.NET MVC:

  • Пользователь получает пустую форму через GET
  • Пользователь отправляет заполненную форму через POST в то же действие
  • Действие проверяет данные, предпринимает соответствующие действия и перенаправляет на новое представление.

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

По какой-то причине у меня есть отвращение к использованию TempData- это что-то, вокруг чего нужно создавать.

Это действительно серьезная проблема, или я выдумываю ее?

анонимный
источник
1
Сделайте шаг подтверждения в виде диалогового окна JavaScript. Меньше обращений к серверу, и вы не столкнетесь с этой проблемой.
ajma

Ответы:

26

Я думаю, что временные данные - это механизм «запустил и забыл» для уведомления пользователя. Замечательно напоминать им о том, что они недавно сделали, но я также не решился бы сделать это обязательным шагом в каком-то пользовательском процессе. Причина в том, что если они обновят страницу, я считаю, что она исчезнет. Что ж, я думаю, я также не решаюсь использовать его, поскольку не совсем точно определено, насколько он надежен.

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

Франк Швитерман
источник
77

Нет нужды испытывать отвращение к TempData ... Но при неправильном использовании это, несомненно, может быть признаком плохого дизайна. Если вы используете URL-адреса RESTful, TempData - лучший способ передачи сообщений из ваших действий POST в действия GET. Учти это:

У вас есть форма по адресу URL Products / New. Форма Сообщает о продуктах / Create, которая проверяет форму и создает продукт, в случае успеха контроллер перенаправляет на URL-адрес Products / 1, а в случае ошибки перенаправляет обратно в продукты / New для отображения сообщений об ошибках.

Products / 1 - это просто стандартное действие GET для продукта, но мы хотели бы, чтобы отображалось сообщение, указывающее, что вставка прошла успешно. TempData идеально подходит для этого. Добавьте сообщение в TempData в Post Controller и добавьте логику if в представление, и все готово.

В случае сбоя я добавлял значения, введенные в formCollection, и набор сообщений об ошибках в TempData в действии публикации и перенаправлял на исходное действие Prodcuts / New. Я добавил в представление логику для заполнения входных данных формы ранее введенными значениями вместе с любыми сообщениями об ошибках. Мне кажется, красиво и чисто!

JasonD
источник
1
Зачем нужна эта дополнительная работа, если вы можете публиковать сообщения прямо на Products/New? Какая ценность Products/Createдобавляет?
mpen
2
@Mark, использование Products / Create предотвращает ситуацию, когда пользователь завершает действие посредством обратной передачи, а затем при более позднем обновлении (или закладке и возврате) случайно повторно завершает действие. Более подробно см en.wikipedia.org/wiki/Post/Redirect/Get
ehdv
3
@ehdv: Но так ли это на самом деле? В случае успеха он перенаправляется на другую страницу, в случае неудачи он должен отображать ошибки формы, и никаких действий предпринимать не должно, поэтому никакого вреда не будет. Это только предотвратит раздражающее сообщение «вы уверены, что хотите повторно опубликовать?», Которое я часто действительно хочу. Думаю, это зависит от вашего дизайна, поэтому я могу понять вашу точку зрения.
mpen
31

Я думаю, вам следует подумать, прежде чем использовать TempData. TempData хранится в сеансе, и это может иметь последствия для вас, если:

  1. Вы сейчас не используете сеансы на своем сайте
  2. У вас есть система, которую необходимо масштабировать до высокой пропускной способности, то есть вы предпочитаете вообще избегать состояния сеанса
  3. Вы не хотите использовать файлы cookie (я не знаю, насколько хорошо MVC сейчас поддерживает сеансы без файлов cookie)

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

Джон Рейнер
источник
16
TempData не обязательно хранить в сеансе, хотя это поставщик по умолчанию - вероятно, поэтому его нет в методической документации. Также есть поставщик файлов cookie, как пример того, как написать собственный поставщик.
FinnNk 08
3

У меня есть метод GetModel, который сначала проверяет TempData ["модель"] и возвращает его. В противном случае GetModel загружает соответствующие данные из базы данных.

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

Тодд Смит
источник
Да, я столкнулся с этим: (1) проверить, существует ли запись, если она действительна, перенаправить на страницу (2) загрузить запись для отображения для пользователя. Таким образом, база данных получает доступ для проверки и отображения. Я почти использую для этого TempData, но мне хотелось проверить мнения. Мне нравится, что ваш метод сдерживает это.
анонимный,
В этом случае было бы лучше использовать правильный механизм кеширования.
nicodemus13
3

Ознакомьтесь с бессессионными контроллерами в MVC3. Оказалось, что использование сеанса предотвращает параллельное выполнение запросов одного пользователя и, таким образом, приводит к снижению производительности.

Поскольку tempdata по умолчанию использует сеанс, вы не сможете использовать эту функцию. Вы можете переключиться на использование файлов cookie для временных данных, но это немного неудобно (по крайней мере, для меня). Тем не менее, он все еще чище, чем viewstate, так что, возможно, это не такой уж большой отказ.

aaimnr
источник
2
Вы правы в отношении контроллеров без сеанса, а TempData использует сеанс. НО ЖДАТЬ! Сессия - это НЕ плохо, и вы можете смешивать и сочетать Sessionless с контроллерами сеанса. Вам действительно нужны контроллеры Session_less_, когда вы выполняете много вызовов AJAX на сервер (из браузера). Когда вы просто открываете одну страницу за раз ... вам не нужно быть без сеанса. Фактически, это НЕ должно дать вам никакой выгоды ... потому что вы только ОДИН РАЗ заходите на сервер. Так что можно смешивать и сочетать.
Pure.Krome 03
2

Почему у вас такое отвращение? Эта штука просто делает свое дело и делает это хорошо :)

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

maxnk
источник
2

Это похоже на использование ViewData, то есть, вероятно, это не угроза безопасности. Но я бы предпочел использовать ViewData, чем TempData. Проверьте здесь для сравнения: http://www.squaredroot.com/2007/12/20/mvc-viewdata-vs-tempdata/

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

Филип Экберг
источник
2
Примечание: статья, на которую вы ссылаетесь, была актуальной для своего времени, но верна только для MVC1. В MVC2 TempData значительно изменилась.
mikemanne
@mikemanne, да. Но ответ датирован концом 2008 года. Но, может быть, ответ следует обновить?
Филип Экберг,
0

Все хорошие ответы, вы смотрели на это для передачи сообщений.

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

При этом взгляните на использование TempData для передачи сообщений здесь.

http://jameschambers.com/2014/06/day-14-bootstrap-alerts-and-mvc-framework-tempdata/

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

Уоррен
источник