ASP.NET: несколько объектов Session в одном приложении - PullRequest
1 голос
/ 06 апреля 2009

У меня есть одно веб-приложение ASP.NET, работающее в корне веб-сервера, которое предоставляет несколько (похожих) веб-сайтов с помощью перенаправления URL. Чтобы привести пример из реального мира:

http://webshopserver/company1/ProductList.aspx -> http://webshopserver/ProductList.aspx?showProductsFrom=company1
http://webshopserver/company2/ProductList.aspx -> http://webshopserver/ProductList.aspx?showProductsFrom=company2
...

Это работает очень хорошо; единственная проблема состоит в том, что, очевидно, все эти разные магазины используют один и тот же объект сеанса (поскольку менеджер сеансов InProc сохраняет объект сеанса в домене приложений). Мне бы хотелось, чтобы магазины company1 и company2 имели разные объекты сеанса, так что, например, если пользователь открывает магазины company1 и company2 на разных вкладках одного и того же окна браузера, элементы, помещенные в корзину компании1, выиграли не отображается в корзине компании2.

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

  • Создайте свой собственный объект Session, который инкапсулирует все в HashMap , а затем сохраняет его в «реальном» сеансе : Это нарушает весь существующий код, который использует объект сеанса.
  • Используйте URL-адреса, такие как http://company1.webshopserver/ и запись DNS с подстановочными знаками, потому что cookie-файл идентификатора сеанса привязан к домену : Это ужасно (поскольку реальный эквивалент «webshopserver» уже существует) достаточно долго).
  • Напишите свой собственный пользовательский поставщик сеансов : Это было бы как изобретать колесо.
  • Создайте отдельное приложение IIS для каждой компании : Не будет работать, потому что создание новых компаний должно быть возможно через что-то вроде http://webshopserver/CreateYourOwnWebshop.aspx без какого-либо вмешательства человека (администратора сервера) впоследствии.

Я подумываю о решении в духе:

  • ограничение пути файла cookie сеанса /" rel="nofollow noreferrer">http://webshopserver// или
  • указание ASP.NET использовать разные домены приложений в зависимости от URL.

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

Ответы [ 4 ]

7 голосов
/ 06 апреля 2009

Не будет ли самым простым решением обновить ссылки на объекты Session, зависящие от компании, с помощью динамического ключа, основанного на Company?

Например ...

Session["IsTest"]

становится

Session[createSessionKey(CompanyID, "IsTest")]

, где createSessionKey генерирует соответствующий ключ, возможно, простым объединением Company и Key

Это тогда дифференцирует две или более компаний, получая доступ к сеансу через сгенерированные ключи.

Следуя приведенному выше примеру, company1 получит доступ к переменной сеанса IsTest через ключ company1_IsTest, а company2 получит доступ к той же переменной сеанса IsTest через ключ company2_IsTest.

Надеюсь, у вас нет таких вещей, как Session ("IsTest"), разбросанных по всей вашей кодовой базе, так как это сделает рефакторинг вашего кода реальной болью.

Обычно я абстрагирую свои переменные Session в строго типизированный класс. Тогда мое управление сессиями содержится в одном месте.

Использование идеи наличия базового класса Page и переопределения свойства Session - хороший способ, если все переменные Session должны относиться к конкретной компании. Хотя, если вы можете определить, является ли конкретный ключ сеанса общей переменной сеанса или конкретной компанией, он все равно может быть работоспособным.

2 голосов
/ 06 апреля 2009

Я предлагаю написать свой собственный сессионный упаковщик. Вот хороший пример из Мартина в другом вопросе:

Как получить доступ к переменным сеанса из любого класса в ASP.NET?

1 голос
/ 06 апреля 2009

Создание вашей собственной оболочки Session или собственного поставщика Session будет правильным ответом. Но вы можете взломать его, переместив существующие данные сеанса, когда пользователь переходит в другую компанию с модулем HttpModule, подключенным к PostAcquireRequestState.

В принципе, сравните эту продукцию от компании с предыдущими продуктами от компании. Если они отличаются, переместите все существующие значения сеанса в Dictionary<string, object> (или добавьте к ним идентификатор компании) и восстановите сохраненный Dictionary<string, object> для этой ProductsFromCompany в Session.

Что-то вроде:

void PostAcquireRequestState(object sender, EventArgs e) {
   if (Session["ProductsFromCompany"] != Request["ProductsFromCompany"]) {
      var lastCompanySession = new Dictionary<string, object>(Session.Count);
      var sessionKeys = Session.Keys;
      foreach (string key in sessionKeys) {
         if (key == "CompanyState" || key == "ProductsFromCompany") {
            continue;
         }
         lastCompanySession[key] = Session[key];
         Session.Remove(key);
      }
      Session["CompanyState"].Add(Session["ProductsFromCompany"], lastCompanySession);

      var thisCompanySession = Session["CompanyState"][Request["ProductsFromCompany"]];
      foreach (string key in thisCompanySession.Keys) {
         Session[key] = thisCompanySession[key];
      }
      Session["CompanyState"].Remove(Request["ProductsFromCompany"]);

      Session["ProductsFromCompany"] = Request["ProductsFromCompany"];
   }
}
1 голос
/ 06 апреля 2009

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

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

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