Як отримати доступ до змінних сеансу з будь-якого класу в ASP.NET?


157

Я створив файл класу в папці App_Code у своїй програмі. У мене змінна сесія

Session["loginId"]

Я хочу отримати доступ до цієї змінної сесії в своєму класі, але коли я пишу наступний рядок, то це дає помилку

Session["loginId"]

Хто-небудь може сказати мені, як отримати доступ до змінних сеансу в межах класу, створеного в папці app_code в ASP.NET 2.0 (C #)

Відповіді:


363

(Оновлено для повноти)
Ви можете отримати доступ до змінних сеансів з будь-якої сторінки або керування за допомогою Session["loginId"]та з будь-якого класу (наприклад, з бібліотеки класів), використовуючиSystem.Web.HttpContext.Current.Session["loginId"].

Але, будь ласка, читайте далі для моєї оригінальної відповіді ...


Я завжди використовую клас обгортки навколо сеансу ASP.NET для спрощення доступу до змінних сеансу:

public class MySession
{
    // private constructor
    private MySession()
    {
      Property1 = "default value";
    }

    // Gets the current session.
    public static MySession Current
    {
      get
      {
        MySession session =
          (MySession)HttpContext.Current.Session["__MySession__"];
        if (session == null)
        {
          session = new MySession();
          HttpContext.Current.Session["__MySession__"] = session;
        }
        return session;
      }
    }

    // **** add your session properties here, e.g like this:
    public string Property1 { get; set; }
    public DateTime MyDate { get; set; }
    public int LoginId { get; set; }
}

Цей клас зберігає один екземпляр себе в сесії ASP.NET і дозволяє вам отримати доступ до властивостей сеансу безпечним для будь-якого класу, наприклад, таким:

int loginId = MySession.Current.LoginId;

string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;

DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;

Цей підхід має ряд переваг:

  • це рятує вас від безлічі типових кастингів
  • Вам не доведеться використовувати жорстко закодовані сеансові ключі протягом усієї програми (наприклад, Session ["loginId"]
  • ви можете задокументувати елементи сеансу, додавши коментарі документів XML щодо властивостей MySession
  • ви можете ініціалізувати змінні сеансу зі значеннями за замовчуванням (наприклад, переконавшись, що вони не є нульовими)

6
Не потрібно писати жодного коду, використовуйте, як показано у відповіді. Наприклад, "public int LoginId {get; set;}" -> це називається автоматичним властивістю.
M4N

4
Якщо ви використовуєте .net 3.x, ви можете використовувати автоматичні властивості, як показано в моєму коді. З .net 2.x / 1.x це недоступно, і ви повинні самостійно реалізувати геттер / сеттер своїх властивостей: private int _loginId; public int LoginId {get {return _loginId; } встановити {_loginId = значення; }}
M4N

2
Зараз виглядає круто, я думаю, що я отримав відповідь на свою проблему, і я завжди використовую ваш спосіб, його дуже чистий і простий в обслуговуванні всіх змінних моїх сеансів в одному місці. Дякую @Martin, ти ДУЖЕ.
Прашант

23
@ M4N, Бажаю, можу висловити трохи більше вдячності, ніж +1. Це стало моїм улюбленим способом роботи із сеансом / кешем у моїх проектах. Мій код, буквально, дякує вам.
Брендон Бун

4
@Kristopher, хоча властивість "Current" є статичною, екземпляр повернутого MySession не є ... так що це добре. Статичні методи та властивості безпечно використовувати таким чином.
Даррен

104

Доступ до сесії через потоки HttpContext: -

HttpContext.Current.Session["loginId"]

Дякую тоні Ентоні за цей простий крок.
Королі

Велике спасибі Ентоні, + 1 за це
Овайс Куреші

Дякую. Забув, який був простір імен :)
Ентоні Хорн

@AnthonyWJones Я використовував ваш метод, але у вас є проблеми, чи можете ви пояснити мені, де я помиляюся або який правильний спосіб використовувати, моє питання stackoverflow.com/questions/45254279/…
adnan

і якщо ви хочете перейти на HttpSessionStateBase: HttpSessionStateBase сесія = новий HttpSessionStateWrapper (HttpContext.Current.Session); Re: stackoverflow.com/questions/5447611 / ...
sobelito

24

Проблема із запропонованим рішенням полягає в тому, що воно може порушити деякі функції продуктивності, вбудовані в SessionState, якщо ви використовуєте сховище сеансу, що не використовується в процесі обробки. (або "Режим державного сервера" або "Режим SQL сервера"). У режимах oop дані сеансу потрібно серіалізувати в кінці запиту на сторінці та десеріалізувати на початку запиту на сторінці, що може дорого коштувати. Для поліпшення продуктивності SessionState намагається десериалізувати лише те, що потрібно лише змінній deserialize, коли до неї звертається вперше, і лише повторно серіалізує та замінює змінну, яка була змінена. Якщо у вас є багато змінних сеансів і перенесіть їх в один клас, по суті все ваші сеанси будуть дезаріалізовані на кожен запит сторінки, що використовує сеанс, і все потрібно буде повторно серіалізувати, навіть якщо змінилося лише 1 властивість, оскільки змінився клас. Просто щось, що варто врахувати, якщо ви використовуєте багато сеансу та режиму oop.


4
+1 для розв’язування цього питання. Якщо ви не використовуєте InProc для сесії, то Ерні на 100% вірно. InProc так чи інакше дуже обмежений, оскільки він не підтримує веб-кадру та втрачається, якщо програма перезапуститься. Зауважте, за вартістю продуктивності ми бачимо 20-відсоткову надбавку у використанні режиму державного сервера, а витрати на серіалізацію додаються до цього. Як ви можете собі уявити, це може дорожче. Ви можете уникнути деяких накладних витрат на серіалізацію, дотримуючись примітивні типи (наприклад, int, string, char, byte тощо). Спеціальні об'єкти зіткнуться з серіалізацією. Користувач остерігайтесь.
Zack Jannsen

+1 Хороший момент. Зміною, яка би вийшла заміж для двох понять, було б, щоб кожне властивість цього звичайного класу "сеансу" викликало саму сесію asp.net замість одного великого об'єкта в сеансі. Доведеться робити типовий кастинг, який уникає підходу @ M4N, але, можливо, того варто, якщо ви кожен раз читаєте лише деякі сеанси.
eol

12

Відповіді, представлені перед моїми, служать правильним рішенням проблеми, проте я вважаю, що важливо зрозуміти, чому ця помилка призводить до цього:

SessionВласність Pageповертає екземпляр типу по HttpSessionStateвідношенню до цього конкретного запиту. Page.Sessionнасправді рівнозначно дзвінкам Page.Context.Session.

MSDN пояснює, як це можливо:

Оскільки сторінки ASP.NET містять за замовчуванням посилання на простір імен System.Web (який містить HttpContextклас), ви можете посилатися на членів HttpContextсторінки .aspx без повної кваліфікації посилання на клас HttpContext.

Однак, коли ви намагаєтеся отримати доступ до цього ресурсу в класі в App_Code, цей ресурс буде недоступний для вас, якщо ваш клас не походить із класу Page Page.

Моє рішення цього часто зустрічається сценарію полягає в тому, що я ніколи не передаю об’єкти сторінки класам . Я б краще витягнути потрібні об'єкти зі сторінки "Сесія" і передати їх Класу у вигляді колекції іменних значень / Масив / Список, залежно від випадку.


Це чудове пояснення, мені це допомогло +1:
Овайс Куреші

1

У мене була така ж помилка, оскільки я намагався маніпулювати змінними сеансу всередині спеціального класу сесії.

Мені довелося передати поточний контекст (system.web.httpcontext.current) в клас, і тоді все вийшло нормально.

МА


1

У ядра asp.net це працює по-різному:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

Джерело: https://benjii.me/2016/07/using-sesions-and-httpcontext-in-aspnetcore-and-mvc-core/


0

Це повинно бути більш ефективним як для програми, так і для розробника.

Додайте до свого веб-проекту такий клас:

/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
    HttpContext.Current.Session[sessionName] = value;
}

protected internal static T Get<T>(string sessionName)
{
    return (T)HttpContext.Current.Session[sessionName];
}

public static int? WhatEverSessionVariableYouWantToHold
{
    get
    {
        return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
    }
    set
    {
        Save(nameof(WhatEverSessionVariableYouWantToHold), value);
    }
}

}

Ось реалізація:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.