2008-09-25 3 views
24

Я хочу сохранить «состояние» некоторых действий, которые пользователь выполняет в серии различных веб-форм ASP.Net. Каковы мои предпочтения в отношении сохраняющегося состояния, и каковы преимущества/недостатки каждого решения?ASP.Net Session

Я использую объекты Session, и используя некоторые вспомогательные методы для сильно типа объектов:

public static Account GetCurrentAccount(HttpSessionState session) 
    { 
     return (Account)session[ACCOUNT]; 
    } 

    public static void SetCurrentAccount(Account obj, HttpSessionState session) 
    { 
     session[ACCOUNT] = obj; 
    } 

Я рассказанные многочисленными источниками, что «Session этого зла», так что на самом деле первопричина этого вопроса. Я хочу знать, что вы думаете о «лучшей практике» и почему.

+1

связанный пост здесь: http://stackoverflow.com/questions/769338/use-of-session-in-high-traffic-websites – MedicineMan 2009-05-05 17:43:06

ответ

38

Нет ничего естественного зла с состоянием сеанса.

Есть несколько вещей, чтобы иметь в виду, что может укусить вас, хотя:

  1. Если пользователь нажимает на кнопку браузера назад вы вернуться на предыдущую страницу, но ваше состояние сеанса не вернулся. Таким образом, ваш CurrentAccount может быть не таким, каким он был на странице.
  2. Процессы ASP.NET могут быть переработаны IIS. Когда это произойдет, следующий запрос начнет новый процесс. Если вы используете в состоянии сеанса процесса, по умолчанию оно не будет :-(
  3. Сессия также может включать тайм-аут с тем же результатом, если пользователь неактивен в течение некоторого времени. Это значение по умолчанию составляет 20 минут, поэтому приятный обед сделают это.
  4. Использование состояния сеанса процесса требует, чтобы все объекты, хранящиеся в состоянии сеанса, были сериализуемыми.
  5. Если пользователь открывает второе окно браузера, он ожидает, что будет иметь второе и отдельное приложение, но состояние сеанса скорее всего, будут разделены между двумя. Таким образом, изменение CurrentAccount в одном окне браузера будет делать то же самое в другом.
6

Что касается «Session is evil» ... если вы разрабатывали классический ASP, я бы согласился, но ASP.NET/IIS выполняет гораздо лучшую работу.

Реальный вопрос - это лучший способ сохранить состояние. В нашем случае, когда речь заходит о текущем зарегистрированном пользователе, мы сохраняем этот объект в сеансе, так как мы постоянно ссылаясь на него для их имени, адреса электронной почты, авторизации и т. Д.

Другие мелкие tidbits информации, которая не требует долговременной стойкости, мы используем комбинацию файлов cookie и viewstate.

10

Насколько я знаю, Session - это способ хранения этой информации. Имейте в виду, что состояние сеанса обычно сохраняется в процессе по умолчанию. Если у вас несколько веб-серверов или перезагрузка IIS, вы теряете состояние сеанса. Это можно устранить, используя государственную службу ASP.NET или даже базу данных SQL для хранения сеансов. Это гарантирует, что люди вернутся к своей сессии, даже если они перенаправлены на другой веб-сервер или в случае передела рабочего процесса.

1

Краткосрочная информация, которая должна жить только до следующего запроса, также может храниться в ViewState. Это означает, что объекты сериализуются и сохраняются на странице, отправленной в браузер, которая затем отправляется обратно на сервер по событию клика или тому подобное. Затем ViewState декодируется и снова превращается в объекты, готовые к восстановлению.

1

Сессии не являются злыми, они служат важной функцией в приложении ASP.NET, обслуживая данные, которые должны совместно использоваться несколькими страницами во время сеанса пользователя. Есть несколько предложений, я бы сказал, что когда-либо можно использовать управление сеансом SQL, и убедитесь, что объекты, которые вы используете в своей коллекции сеансов, являются «сериализуемыми». Лучшей практикой будет использование объекта сеанса, когда вам абсолютно необходимо обмениваться информацией о состоянии на разных страницах и не использовать его, когда вам это не нужно. Информация не будет доступна на стороне клиента. Ключ сеанса хранится либо в файле cookie, либо в строке запроса, либо с использованием других методов в зависимости от того, как он настроен, а затем объекты сеанса доступны в таблице базы данных (если вы не используете InProc, и в этом случае ваши сеансы будут иметь возможность сдуться во время перезагрузки сайта или будут практически бесполезны в большинстве кластерных сред).

2

http://www.tigraine.at/2008/07/17/session-handling-in-aspnet/

надеюсь, что это помогает.

+0

Я бы сказал, что ссылка не соответствует духу SO , – Kristopher 2015-09-23 12:24:51

+0

Да и нет. Нет смысла повторять информацию, поскольку все объяснение не имеет смысла в ответе. Но я согласен, что мог бы немного подвести итог и предоставить ссылку – Tigraine 2015-09-23 22:21:13

1

Сессия как зло: не в ASP.NET, правильно настроена. Да, это идеальный вариант, чтобы быть как можно более независимым, но реальность такова, что вы не можете добраться туда отсюда. Однако вы можете заставить сеанс вести себя так, чтобы уменьшить его влияние - особенно на сеансы StateServer или базы данных.

+0

ваши ссылки не работают ... – TheEmirOfGroofunkistan 2009-08-11 19:26:32

+0

Да, к сожалению, этот сайт не работает. Хороший звонок; Я убиваю ссылки. – 2009-08-11 20:06:38

5

Если вы хотите хранить информацию, доступную глобально в своем веб-приложении, способ сделать это - это атрибут ThreadStatic. Это превращает static член Class в элемент, который совместно используется текущим потоком, но не другими потоками. Преимущество ThreadStatic состоит в том, что вам не нужно иметь доступный веб-контекст. Например, если у вас есть обратный конец, который не ссылается на System.Web, но вы хотите также обмениваться информацией, вы можете установить id пользователя в начале каждого запроса в свойстве ThreadStatic и ссылаться на него в своей зависимости без необходимости доступа к объекту Session.

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

3

Я думаю, что использование объекта Session в этом случае в порядке, но вы должны помнить, что сеанс может истекать, если в течение длительного времени нет активности браузера (HttpSessionState.Timeout свойство определяет, сколько минут оператор сеансового состояния завершает сеанс), так что это лучше проверить наличие стоимости до возврата:

public static Account GetCurrentAccount(HttpSessionState session) 
{ 
    if (Session[ACCOUNT]!=null) 
     return (Account)Session[ACCOUNT]; 
    else 
     throw new Exception("Can't get current account. Session expired."); 
} 
1

Я думаю, что «зло» происходит от чрезмерного использования сеанса. Если вы просто вставляете что-либо и все в нем (например, используя глобальные переменные для всего), вы получите плохую производительность и просто беспорядок.

6

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

19

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

Использование переменных (ов) сеанса является классическим решением этой проблемы, но оно имеет несколько недостатков. Среди них: (1) большие объемы данных могут использовать серверную ОЗУ, если вы используете управление сеансом inproc, (2) разделение переменных сеанса на нескольких серверах в ферме серверов требует дополнительных соображений и (3) профессионально разработанное приложение должно защищать от истечения срока действия сеанса (не просто передавать переменную сеанса и использовать ее - если срок действия сеанса истек, приведение бросает ошибку). Однако для подавляющего большинства приложений, переменные сессии, бесспорно путь.

Альтернативой является передача информации каждой формы в URL. Основная проблема с этим подходом заключается в том, что вам нужно быть предельно осторожным в отношении «прохождения» информации. Например, если вы собираете информацию на четырех страницах, вам нужно будет собрать информацию в первую очередь, передать ее в URL-адрес на вторую страницу, где вы должны сохранить ее в окне просмотра этой страницы. Затем, вызывая третью страницу, вы будете собирать данные формы со второй страницы плюс переменные viewstate и кодировать как в URL-адресе, так и т.д. Если у вас есть пять или более страниц или если посетитель будет прыгать по сайту, вы У тебя будет настоящий беспорядок на твоих руках. Имейте в виду также, что вся информация должна быть A) должна быть сериализована в строку с безопасным URL-адресом и B) закодирована таким образом, чтобы предотвратить простые хаки на основе URL-адресов (например, если вы поместили цену в ясный текст и передали ее вместе, кто-то может изменить цену). Обратите внимание, что вы можете уменьшить некоторые из этих проблем, создав своего рода «диспетчер сеансов» и попросите его управлять строками URL-адресов для вас, но вы все равно должны быть чрезвычайно чувствительны к возможности того, что любая данная ссылка может сбить весь сеанс пользователя, если он не управляется должным образом.

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

Предположим, что вы действительно будете управлять данными пользователя, используя встроенные возможности сеансов. Почему кто-то скажет вам, что «Сессия зла»? Ну, в дополнение к рассмотренной выше нагрузке на память, серверной ферме и соображениям истечения, первичной критикой переменных сеанса, которые они являются, фактически, нетипизированными переменными.

К счастью, разумное использование переменных сеанса может избежать проблем с памятью (в любом случае большие базы данных должны храниться в базе данных), и если вы используете сайт, достаточно большой для работы фермы серверов, существует множество механизмов для совместного использования состояния встроенный в ASP.NET (подсказка: вы не будете использовать хранилище inproc).

Чтобы избежать практически всех остальных недостатков сеанса, я рекомендую реализовать объект для хранения данных сеанса, а также для некоторых простых функций управления объектами сеанса. Затем создайте их в потомке класса «Страница» и используйте этот дочерний класс страницы для всех ваших страниц. Тогда просто получить доступ к вашим данным сеанса через класс страницы в виде набора строго типизированных значений. Обратите внимание, что поля вашего объекта предоставят вам доступ к каждой из ваших «переменных сеанса» строго типизированным образом (например, по одному полю для каждой переменной).

Сообщите мне, если это простая задача для вас или если вы хотите получить образец кода!

1

Все, что вы помещаете в объект сеанса, остается там на время сеанса, если оно не очищено. Плохое управление памятью, хранящейся с использованием inproc и stateserver, заставит вас масштабировать раньше, чем это необходимо. Храните только идентификатор сеанса/пользователя в сеансе и загружайте то, что необходимо в объект кеша по требованию, используя вспомогательный класс. Таким образом, вы можете точно настроить свою жизнь в зависимости от того, как часто эти данные мы использовали. Следующая версия asp.net может иметь распределенный кеш (слух).

0

Что такое сеанс в веб-приложении?

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