Предотвращение истечения отдельных сеансов на основе пользовательских условий?

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

Все отношения отчета/пользователя сохраняются в переменной приложения. Это работает отлично, за исключением случаев, когда пользователь неактивен более 20 минут (во время обработки отчета), а затем пользователь выходит из системы; если пользователь снова войдет в систему, отчет можно будет загрузить.

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

В Session_End я могу получить userid и сопоставить его в Application["work"], чтобы увидеть, что у пользователя есть работа или нет.

Однако я не знаю, как я могу отложить сеанс в приведенном выше случае?


Изменить:. Каждый из них предложил в качестве обходного пути от "поддержания контакта" до "использования строки запроса". "Поддержание контакта" выглядело наиболее перспективным для меня, но оно не срабатывало в следующих сценариях: a. Когда браузер закрыт/вычислен, он переходит в режим ожидания во время обеда и т.д. B. Когда пользователь переходит к другому разделу nonasp.net(это старый сайт).

Невозможно ли отменить событие Session_End?

Ответ 1

Пока отчаянно ищет отсрочку события session_end, я думаю, что это кажется невозможным?

Простейшей работой, с которой я смог связаться, было "Использование Cookies" и изменение моей логики аутентификации.

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

На главной странице, где я просматривал сеанс userid, я применил другой метод для проверки cookie с именем admin. Если он найден, я назначил сеанс идентификатору пользователя, сохраненному в таблице. Я перенаправляю их на страницу входа, как раньше.

Кажется, он работает как магия. Но мне нужно знать, правильно ли это?

Ответ 2

Короткий ответ

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


Длинный ответ

Прежде всего: Начните с того, что уже построено! Используйте образец Поставщик хранилища состояний сеанса (и его учебник), предоставленный Microsoft. Этот пример поставщика хранилища состояний сеанса использует Microsoft Access в качестве его задней части; хотя, поскольку он использует соединения ODBC, вы можете иметь практически любую базу данных, поддерживаемую с помощью установленных драйверов ODBC.

Этот пример поставщика хранилища состояний сеансов - это просто настраиваемая версия того, что использует ASP.NET внутри (за исключением того, что ASP.NET работает в оперативной памяти).


Во-вторых:. Подготовьте требования к базе данных Access и конфигурацию.

Создайте таблицу, указанную в учебнике и в комментариях файла:

CREATE TABLE Sessions
(
    SessionId       Text(80)  NOT NULL,
    ApplicationName Text(255) NOT NULL,
    Created         DateTime  NOT NULL,
    Expires         DateTime  NOT NULL,
    LockDate        DateTime  NOT NULL,
    LockId          Integer   NOT NULL,
    Timeout         Integer   NOT NULL,
    Locked          YesNo     NOT NULL,
    SessionItems    Memo,
    Flags           Integer   NOT NULL,

    CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
)

ПРИМЕЧАНИЕ. Если вы хотите использовать SQL Server, просто замените Текст (...) на varchar (...), YesNo с бит и Заметка с varchar (MAX).

Добавьте/обновите свой web.config следующим образом (вы можете использовать connectionstrings.com, чтобы помочь вам создать строку соединения):

<configuration>
    <connectionStrings>
        <add name="OdbcSessionServices" connectionString="DSN=SessionState;" />
    </connectionStrings>

    <system.web>
        <sessionState 
                cookieless="true"
                regenerateExpiredSessionId="true"
                mode="Custom"
                customProvider="OdbcSessionProvider">
            <providers>
                <add name="OdbcSessionProvider"
                        type="Samples.AspNet.Session.OdbcSessionStateStore"
                        connectionStringName="OdbcSessionServices"
                        writeExceptionsToEventLog="false" />
            </providers>
        </sessionState>
    </system.web>
</configuration>

В-третьих: Добавление функции, которая будет расширяться более чем на Timeout.

Сделайте копию функции ResetItemTimeout и назовите ее ResetItemTimeout2:

var ExtendedTotalMinutes = 2 * 60; // hours * minutes

public override void ResetItemTimeout2(HttpContext context, string id)
{
    OdbcConnection conn = new OdbcConnection(connectionString);
    OdbcCommand cmd = 
        new OdbcCommand("UPDATE Sessions SET Expires = ? " +
            "WHERE SessionId = ? AND ApplicationName = ?", conn);
    cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value 
        = DateTime.Now.AddMinutes(ExtendedTotalMinutes); // IMPORTANT!! Set your total expiration time.
    cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
    cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;

    try
    {
        conn.Open();

        cmd.ExecuteNonQuery();
    }
    catch (OdbcException e)
    {
        if (WriteExceptionsToEventLog)
        {
            WriteToEventLog(e, "ResetItemTimeout");
            throw new ProviderException(exceptionMessage);
        }
        else
            throw e;
    }
    finally
    {
        conn.Close();
    }
}

Четвертый: Поддержка расширения одного сеанса ASP.NET!

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

using Samples.AspNet.Session;

// from inside a User Control or Page
OdbcSessionStateStore.ResetItemTimeout2(this.Context, this.Session.SessionID);

// --or--

// from anywhere else
OdbcSessionStateStore.ResetItemTimeout2(System.Web.HttpContext.Current, System.Web.HttpContext.Current.Session.SessionID);

Сноска

  • Прочитайте комментарии на странице с образцом поставщика хранилища состояний сеанса;

    • Существует одна потенциальная хорошая запись о ошибке в GetSessionStoreItem при использовании GetItem.

    • Другим хорошим является то, что Временные метки должны быть UTC.

  • Есть очевидные улучшения производительности/ремонтопригодности, которые могут быть выполнены (особенно с дублированием кода в ResetItemTimeout и ResetItemTimeout2).

  • У меня не проверен этот код!


редактирует

  • Я понял, что пропустил ту часть, где вы хотите продлить больше, чем Timeout - ответ был полностью обновлен.
  • Добавлен раздел сносок.

Ответ 3

Maintain a contact with the server will avoid Session Timeout. 

Создайте empty Web service и run that in your server, а затем call the web service by your site by JQuery с интервалом в несколько секунд, чтобы сохранить сеанс в

Возможно, это решение поможет вам.

Прочтите эту ссылку для получения полной информации: Предотвратить тайм-аут сеанса в ASP.NET

Ответ 4

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

Session.Timeout = 120 // set timeout to two hours for this session only

Помимо прокрутки страницы или сервиса через Ajax, другого пути нет. (если только не полагаться на сеансы вообще - это вариант).

Это связано с тем, что сеансы поддерживаются: среда выполнения ASP.NET обнаруживает сеанс, когда запрос содержит файл cookie. Этот файл cookie устанавливается при каждом запросе/ответе и будет содержать дату истечения срока действия.

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

Решение, которое я предложил, является обходным решением, которое может работать, если вы знаете, как рассчитать продолжительность (по крайней мере, примерно).

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

Ответ 5

Лучше не полагаться на Session_end, поскольку он не всегда срабатывает, например, когда рабочий процесс перерабатывается или происходит неперехваченное исключение, т.е. он в основном убит/отскок.

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

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

P.S. В общем, покончить с сессиями, похоже, будет самым эффективным решением, см. Ответ Джона Хан в этом посте, просто подводит итоги сеансы плохой MMKAY.

Ответ 6

Чтобы сеанс оставался в живых, что-то (не обязательно браузер пользователя) должно делать запрос к вашему приложению с этим пользователем ASP.NET_SessionId cookie так часто.

Что делать, если у вас есть код, который сохраняет ASP.NET_SessionIds пользователей, которых вас интересует, а затем у вас есть служба Windows, которая запрашивает страницу в вашем приложении с требуемыми ASP.NET_SessionId (s) каждые 20 минут или около того.

см. http://erlend.oftedal.no/blog/?blogid=41 для получения информации об этом файле cookie

Ответ 7

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

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

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

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

Тайм-аут для аутентификационного билета довольно большой http://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration.timeout.aspx

Приветствия

Ответ 8

Я предлагаю увеличить тайм-аут сеанса вместо того, чтобы пытаться найти способ обойти его. Там интересная тема о сеансах и тайм-аутах формы здесь

Ответ 9

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

Ответ 10

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