Как получить доступ к значениям сеанса из слоев ниже уровня веб-приложения

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

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


person Matthew Vines    schedule 23.04.2010    source источник
comment
Какая разница за 8 лет. В наши дни тривиально легко обернуть любые требования сеанса в интерфейс и использовать свой контейнер DI, чтобы внедрить его там, где это необходимо.   -  person Matthew Vines    schedule 01.06.2018


Ответы (3)


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

Поэтому вместо того, чтобы передавать объект Session напрямую им, вы должны заключить необходимые вам методы доступа к информации в класс репозитория. Ваш бизнес-уровень может использовать класс репозитория в качестве источника данных (например, вызвать GetUser()), а репозиторий вашего веб-приложения может использовать сеанс для получения запрошенной информации (возврат _session.User.Identity).

При переносе на winforms просто реализуйте интерфейс репозитория с новым классом, ориентированным на winform (т.е. GetUser() возвращает версию пользователя в Windows).

person womp    schedule 23.04.2010

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

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

public interface ISessionStorage 
{
   SomeSessionData Data {get;set;}
   ...
   .. and most of the data we need stored at "session" level
    }
 //and a singleton to access it
    public static ISessionStorage ISessionStorage;

этот интерфейс доступен практически из любого места в нашем коде.

Тогда у нас есть как сеанс, так и / или одноэлементная реализация

 public WebSessionStorage
{
   public SomeSessionData Data 
  {
       get { return HttpContext.Current.Session["somekey"] as SomeSessionData;}
      set { HttpContext.Current.Session["somekey"] = value;}
  }

public WebFormsSessionStorage
{
   private static SomeSessionData  _SomeSessionData; //this was before automatic get;set;
   public SomeSessionData 
   {
       get{ return _SomeSessionData;}
       set{ _SomeSessionData=value; }
}

}

При запуске приложения сайт выполнит

 Framework.Storage.SessionStorage = new WebSessionStorage(); 

в Global.asax, и FormsApp сделает

 Framework.Storage.SessionStorage = new WebFormsSessionStorage(); 
person Radu094    schedule 24.04.2010

Я полностью согласен с Womp - вводите данные из вашего интерфейса в ваши нижние уровни.

Если вы хотите наполовину обмануть (но не слишком много), вы можете создать очень маленькую сборку всего с парой классы POCO для хранения всей этой информации, которую вы хотите передать на всех своих уровнях (имя пользователя, вошедшего в систему, время входа в систему и т. д.), и просто передайте этот объект из своего интерфейс на ваших уровнях бизнеса / данных. Теперь, если вы сделаете это, вы ДОЛЖНЫ избежать соблазна превратить эту сборку POCO в общую служебную сборку - она ​​ДОЛЖНА оставаться небольшой, иначе у вас БУДУТ проблемы в будущем (поверьте мне, или научитесь на собственном опыте, или попросите кого-нибудь подробнее рассказать об этом один). Однако, если у вас есть эта сборка POCO, внедрение этих данных через различные уровни становится очень простым, и, поскольку это POCO, он очень хорошо сериализуется и отлично работает с веб-службами, WCF и т. Д.

person Jaxidian    schedule 24.04.2010