Сессия ASP.Net

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

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

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

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

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


person Steve Horn    schedule 25.09.2008    source источник
comment
связанное сообщение здесь: http://stackoverflow.com/questions/769338/use-of-session-in-high-traffic-websites   -  person MedicineMan    schedule 05.05.2009


Ответы (13)


В состоянии сеанса нет ничего плохого по своей сути.

Однако следует помнить о нескольких вещах, которые могут вас укусить:

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

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

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

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

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

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

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

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

Дайте мне знать, если это простая задача для вас или вам нужен образец кода!

person Mark Brittingham    schedule 25.09.2008

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

person Kamiel Wanrooij    schedule 25.09.2008

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

person alexis.kennedy    schedule 25.09.2008

Что касается «Сессия зла» ... если бы вы разрабатывали в классическом ASP, я бы согласился, но ASP.NET/IIS работает намного лучше.

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

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

person mattruma    schedule 25.09.2008

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

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

person Kamiel Wanrooij    schedule 25.09.2008

Я думаю, что использование объекта 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.");
}
person Alexander Prokofyev    schedule 25.09.2008
comment
Я бы не стал генерировать исключение, вы могли бы просто загрузить объект сеанса (т.е. лениво загрузить его). - person Greg Ogle; 25.09.2008
comment
Исключение в коде, конечно, только для привлечения внимания. В случае необходимости его следует заменить. - person Alexander Prokofyev; 26.09.2008

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

надеюсь это поможет.

person Tigraine    schedule 25.09.2008
comment
Я бы сказал, что ссылка не соответствует духу SO. - person Kristopher; 23.09.2015
comment
И да и нет. Нет смысла повторять информацию, поскольку все объяснение не имеет смысла в ответе. Но я согласен, что мог бы немного резюмировать и дать ссылку - person Tigraine; 24.09.2015

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

person Kamiel Wanrooij    schedule 25.09.2008

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

person stephenbayer    schedule 25.09.2008

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

person Greg Ogle    schedule 25.09.2008

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

person Community    schedule 29.09.2008

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

person John Rudy    schedule 25.09.2008
comment
Да, к сожалению, этот сайт не работает. Хороший звонок; Убиваю ссылки. - person John Rudy; 12.08.2009