2013-04-01 3 views
10

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

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

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

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

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


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

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

ответ

3

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

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

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

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

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

1

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

+2

Зачем мне увеличивать тайм-аут сеанса ?? Мне просто нужны они для 2 или 3 пользователей, которые также через неделю. Разве вы не думаете, что это будет пустая трата ресурсов? когда 99% пользовательского дозатора требуют длительной сессии. – Ratna

4
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 интервала в несколько секунд достаточно, чтобы сохранить сессию живого

Может быть, это решение поможет вам ..

Попробуйте эту ссылку для получения подробной информации: Prevent Session Timeout in ASP.NET

+0

На моей странице загрузки уже установлен таймер ajax, который обновляет страницу за 5 минут. Howerver администраторы имеют привычку делать другие вещи, которые меняют расположение страницы. – Ratna

1

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

+0

Уважаемый самир, я не чувствую, что это будет возможно, так как мне придется изменить весь код аутентификации. Проблема заключается не только в загрузке файла. Администратор иногда объединяет 2 или более файлов перед отправкой на amazon, для чего я должен отслеживать все созданные им файлы. – Ratna

+0

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

1

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

+0

И как это будет работать, когда пользователь перейдет на другой сайт? (как указывал ОП) –

4

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

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

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

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

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

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

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

5

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

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


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

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

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


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

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

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 с немного и Memo с 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); 

Сноски

  1. Прочитайте comments на странице с образцом Провайдер хранилища состояния сеанса;

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

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

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

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


редактирует

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

Джесси Я попытался его реализовать, но значительно увеличил время загрузки. – Ratna

+0

Вы пытались использовать SQL в качестве бэкэнд вместо MS Access? Как насчет использования 'SqlConnection' вместо' OdbcConnection' (заменить все Odbc на Sql)? – Jesse

+0

весь наш проект находится на ms sql, поэтому нет необходимости использовать его как acess. на самом деле мы ввели этот b4 также потому, что нам нужно было передавать значения сеанса между классическими asp и asp.net. – Ratna

2

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

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

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

2

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

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

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

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

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

Приветствия

3

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

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

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

P.S. В общем, отключение сессий казалось бы самым эффективным решением, см. Ответ Джона Ханна в этом сообщении, как раз о сумме его sessions are bad mmkay.