Внедрение зависимостей ASP.NET MVC с состоянием сеанса UnityContainer - PullRequest
2 голосов
/ 11 июня 2009

У меня есть веб-сайт asp.net mvc, где я использую функции инъекций зависимостей в «Micorosoft.Practices.Unity» и «Microsoft.Practices.ObjectBuilder2». Все это прекрасно работает, поскольку мои объекты вводятся в конструкторы контроллеров.

Проблема в том, что у меня возникают трудности при очистке этого сеанса, когда пользователь покидает браузер или хочет выйти из системы. Все значения сохраняются в объектах. Как я могу уничтожить контейнер, созданный в global.asax, либо по Session_End(), либо по щелчку пользователя и выполнению действия контроллера

Ниже приведен пример кода.

Global.asax - Выполнено с Session_start:

protected static void RegisterDependencies()
{
    IUnityContainer container = new UnityContainer();

    container.RegisterType<DataStore, DataStore>(new SessionLifetimeManager<DataStore>());
    container.RegisterType<IMotorRepository, MotorRepository>(new SessionLifetimeManager<IMotorRepository>());
    container.RegisterType<ICoverRepository, CoverRepository>(new SessionLifetimeManager<ICoverRepository>());
    container.RegisterType<IDriverRepository, DriverRepository>(new SessionLifetimeManager<IDriverRepository>());
    container.RegisterType<IVehicleRepository, VehicleRepository>(new SessionLifetimeManager<IVehicleRepository>());
    container.RegisterType<ICodeValueRepository, CodeValueRepository>(new SessionLifetimeManager<ICodeValueRepository>());

    ControllerBuilder.Current.SetControllerFactory(
        new UnityControllerFactory(container)
    );
}

SessionLifeTimeManager:

public class SessionLifetimeManager<T> : LifetimeManager, IDisposable
{
    public override object GetValue()
    {
        return HttpContext.Current.Session[typeof(T).AssemblyQualifiedName];
    }
    public override void RemoveValue()
    {
        HttpContext.Current.Session.Remove(typeof(T).AssemblyQualifiedName);
    }
    public override void SetValue(object newValue)
    {
        HttpContext.Current.Session[typeof(T).AssemblyQualifiedName] = newValue;
    }
    public void Dispose()
    {
        RemoveValue();
    }
}

Ответы [ 2 ]

0 голосов
/ 19 февраля 2010

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

Действительно, вам не нужно делать и то, и другое. Любой из регистров связывает контейнер с сеансом ИЛИ устанавливает время жизни объекта в сеанс.

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

0 голосов
/ 12 июня 2009

Session_End не запускается примерно до 30 минут после того, как пользователь уходит. Я тоже встретил беду сессии в ASP.NET.

Если вы вызываете Session.Abandon, вы можете запустить Session_end. Но это не решит вашу проблему, если пользователь покидает ваш сайт или закрывает браузер.

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

Проблема с этим? Это истечет сеанс КАЖДЫЙ переход страницы.

window.onbeforeunload = endSession;

function endSession() {
    //end session here through some kind of call back to the server
}

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

var endUserSession = true;

window.onbeforeunload = endSession;

function endSession() {
    if(endUserSession) {
        //end session here through some kind of call back to the server
    }
}

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

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

Если проблема здесь связана с доступными системными ресурсами: т. Е. Сайт просто занимает много памяти и сеанс дампа не подходит, вы можете реализовать Sql Server State Server, а затем перезапустить рабочий процесс так, как вам нужно. .

Как реализовать SQL Server State Server

...