Переменные сеанса в ASP.NET MVC

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

Ответ 1

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

в global.asax подключить событие OnSessionStart

void OnSessionStart(...)
{
    HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}

Из любого места в коде, где свойство HttpContext.Current!= null, вы можете извлечь этот объект. Я делаю это с помощью метода расширения.

public static MySessionObject GetMySessionObject(this HttpContext current)
{
    return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}

Таким образом вы можете в коде

void OnLoad(...)
{
    var sessionObj = HttpContext.Current.GetMySessionObject();
    // do something with 'sessionObj'
}

Ответ 2

Ответ здесь правильный, однако я старался реализовать его в приложении ASP.NET MVC 3. Я хотел получить доступ к объекту Session в контроллере и не мог понять, почему я продолжал получать "экземпляр, не установленный в экземпляр ошибки объекта". Я заметил, что в контроллере, когда я пытался получить доступ к сеансу, выполнив следующее, я продолжал получать эту ошибку. Это связано с тем, что this.HttpContext является частью объекта Controller.

this.Session["blah"]
// or
this.HttpContext.Session["blah"]

Однако, я хотел, чтобы HttpContext был частью пространства имен System.Web, потому что это тот, который предлагает вышеприведенный ответ в Global.asax.cs. Поэтому я должен был явно сделать следующее:

System.Web.HttpContext.Current.Session["blah"]

это помогло мне, не уверен, что я сделал что-то, что не было М. О. здесь, но я надеюсь, что это поможет кому-то!

Ответ 3

Поскольку мне не нравится видеть "HTTPContext.Current.Session" о месте, я использую одноэлементный шаблон для доступа к переменным сеанса, он дает вам простой доступ к строго типизированному пакету данных.

[Serializable]
public sealed class SessionSingleton
{
    #region Singleton

    private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";

    private SessionSingleton()
    {

    }

    public static SessionSingleton Current
    {
        get
        {
            if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
            {
                HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
            }

            return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
        }
    }

    #endregion

    public string SessionVariable { get; set; }
    public string SessionVariable2 { get; set; }

    // ...

то вы можете получить доступ к своим данным из любого места:

SessionSingleton.Current.SessionVariable = "Hello, World!";

Ответ 4

Если вы используете asp.net mvc, вот простой способ получить доступ к сеансу.

От контроллера:

{Controller}.ControllerContext.HttpContext.Session["{name}"]

Из представления:

<%=Session["{name}"] %>

Это определенно не лучший способ получить доступ к вашим переменным сеанса, но это прямой маршрут. Поэтому используйте его с осторожностью (желательно во время быстрого прототипирования) и используйте Wrapper/Container и OnSessionStart, когда это станет подходящим.

НТН

Ответ 5

Ну, ИМХО..

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

Что касается № 1, у меня есть строго типизированный Master View, у которого есть свойство для доступа к тому, что представляет объект Session... в моем примере сильно типизированный Master View является общим, что дает мне некоторую гибкость в отношении напечатанные страницы просмотра

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

AdminViewModel<TModel> : AdminViewModel where TModel : class
{
   TModel Content
}

а затем...

ViewPage<AdminViewModel<U>>

Ответ 6

Хотя я не знаю о asp.net mvc, но это то, что мы должны делать на обычном веб-сайте .net. Он также должен работать для asp.net mvc.

YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}

Вы бы поставили это внутри метода для легкого доступа. НТН

Ответ 7

Есть 3 способа сделать это.

  • Вы можете напрямую получить доступ к HttpContext.Current.Session

  • Вы можете Mock HttpContextBase

  • Создайте метод расширения для HttpContextBase

Я предпочитаю третий способ. Эта ссылка является хорошей ссылкой.

Получить/установить методы сеанса HttpContext в BaseController и Mocking HttpContextBase для создания методов Get/Set

Ответ 8

Отличные ответы от ребят, но я бы предостерег вас от того, чтобы всегда полагаться на Сессию. Это быстро и легко сделать, и, конечно, это сработает, но не будет здорово во всех случаях.

Например, если вы используете сценарий, в котором ваш хостинг не разрешает использование сеанса, или если вы находитесь в веб-ферме или в примере общего приложения SharePoint.

Если вы хотите другое решение, вы можете посмотреть, как использовать контейнер IOC Container, например Castle Windsor, создавая класс поставщика в качестве обертки, а затем сохраняя один экземпляр вашего класса с использованием каждого запроса или стиля сеанса в зависимости от ваших требований.

IOC гарантирует, что один и тот же экземпляр будет возвращен каждый раз.

Сложнее да, если вам нужно простое решение, просто используйте сеанс.

Ниже приведены примеры реализации ниже.

С помощью этого метода вы можете создать класс поставщика по строкам:

public class CustomClassProvider : ICustomClassProvider
{
    public CustomClassProvider(CustomClass customClass)
    { 
        CustomClass = customClass;
    }

    public string CustomClass { get; private set; }
}

И зарегистрируйте что-то вроде:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
            Component.For<ICustomClassProvider>().UsingFactoryMethod(
                () => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
    }

Ответ 9

Вы можете использовать ViewModelBase в качестве базового класса для всех моделей, этот класс позаботится о выводе данных из сеанса

class ViewModelBase 
{
  public User CurrentUser 
  {
     get { return System.Web.HttpContext.Current.Session["user"] as User };
     set 
     {
        System.Web.HttpContext.Current.Session["user"]=value; 
     }
  }
}

Вы можете написать метод расширения для HttpContextBase для обработки данных сеанса

T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null) 
{
    if(context.Session[key]!=null) 
    {
        return (T) context.Session[key];
    }
  else if(getFromSource!=null) 
  {
    var value = getFromSource();
   context.Session[key]=value; 
   return value; 
   }
  else 
  return null;
}

Используйте это, как показано ниже в контроллере

User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db  }); 

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

Ответ 10

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

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;

namespace dmkp
{
    /// <summary>
    /// Encapsulates the session state
    /// </summary>
    public sealed class LoginInfo
    {
        private HttpSessionState _session;
        public LoginInfo(HttpSessionState session)
        {
            this._session = session;
        }

        public string Username
        {
            get { return (this._session["Username"] ?? string.Empty).ToString(); }
            set { this._session["Username"] = value; }
        }

        public string FullName
        {
            get { return (this._session["FullName"] ?? string.Empty).ToString(); }
            set { this._session["FullName"] = value; }
        }
        public int ID
        {
            get { return Convert.ToInt32((this._session["UID"] ?? -1)); }
            set { this._session["UID"] = value; }
        }

        public UserAccess AccessLevel
        {
            get { return (UserAccess)(this._session["AccessLevel"]); }
            set { this._session["AccessLevel"] = value; }
        }

    }
}