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

157

Я создал файл класса в папке App_Code в моем приложении. У меня есть переменная сеанса

Session["loginId"]

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

Session["loginId"]

Может кто-нибудь сказать мне, как получить доступ к переменным сеанса в классе, который создается в папке app_code в ASP.NET 2.0 (C #)

Prashant
источник

Ответы:

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
  • вы можете инициализировать переменные сеанса значениями по умолчанию (например, убедившись, что они не равны NULL)
M4N
источник
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; } set {_loginId = value; }}
M4N
2
Выглядит здорово, я думаю, что я получил ответ на мою проблему, и я уже использую ваш способ, он очень чистый и простой, чтобы поддерживать все мои переменные сеанса в одном месте. Спасибо @Martin, ты УДИВИТЕЛЬНЫЙ.
Прашант
23
@ M4N, Жаль, что я не могу выразить больше благодарности, чем +1. Это стало моим любимым способом работы с сессией / кэшем в моих проектах. Мой код буквально благодарит вас.
Брэндон Бун
4
@Kristopher, в то время как свойство Current является статическим, экземпляр MySession возвращается не ... так что все в порядке. Статические методы и свойства безопасны для использования таким образом.
Даррен
104

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

HttpContext.Current.Session["loginId"]
AnthonyWJones
источник
Спасибо большое Энтони за этот простой шаг.
Kings
Большое спасибо Энтони, +1 за это
Оваис Куреши
Спасибо. Забыли, что было пространство имен :)
Энтони Хорн
@AnthonyWJones Я использовал твой метод, но у меня возникла проблема, можешь ли ты объяснить мне, где я ошибаюсь или какой правильный способ использовать мой вопрос stackoverflow.com/questions/45254279/…
adnan
и если вы хотите преобразовать в HttpSessionStateBase: HttpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/…
sobelito
24

Проблема с предлагаемым решением заключается в том, что оно может нарушить некоторые функции производительности, встроенные в SessionState, если вы используете хранилище сеансов вне процесса. (либо «Режим сервера состояний», либо «Режим сервера SQL»). В режиме oop данные сеанса должны быть сериализованы в конце запроса страницы и десериализованы в начале запроса страницы, что может быть дорогостоящим. Для повышения производительности SessionState пытается десериализовать только то, что необходимо, только десериализовать переменную при первом обращении к нему, и он только повторно сериализует и заменяет переменную, которая была изменена. Если у вас есть много переменных сеанса и они объединены в один класс, то, по сути, все в вашем сеансе будет десериализовано при каждом запросе страницы, который использует сеанс, и все будет необходимо снова сериализовать, даже если изменилось только 1 свойство, так как класс изменился. Просто что-то, чтобы рассмотреть, если вы используете много сеанса и режим oop.

Эрни
источник
4
+1 за это. Если вы не используете InProc для сессии, то Эрни на 100% прав. В любом случае InProc очень ограничен, так как не поддерживает веб-фермы и будет утерян, если приложение перезапустится. Обратите внимание, что при снижении производительности мы рассчитываем на 20% при использовании режима State Server, и к этому добавляются затраты на сериализацию. Как вы можете себе представить, это может стать дорогим. Вы можете избежать некоторых издержек сериализации, придерживаясь примитивных типов (например, int, string, char, byte и т. Д.). Пользовательские объекты столкнутся с сериализацией. Пользователь остерегается.
Зак Яннсен
+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, это свойство не будет вам доступно, если ваш класс не является производным от класса страницы.

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

Cerebrus
источник
Это отличное объяснение, это помогло мне +1 за это :)
Owais Qureshi
1

У меня была та же ошибка, потому что я пытался манипулировать переменными сеанса внутри пользовательского класса Session.

Я должен был передать текущий контекст (system.web.httpcontext.current) в класс, а затем все работало нормально.

Массачусетс

MunsterMan
источник
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-sessions-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;
Капитан Америка
источник