Вопрос

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

Это было полезно?

Решение

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

в 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'
}

Другие советы

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

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

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

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

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

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

[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!";

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

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

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

С точки Зрения:

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

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

HTH

Ну, ИМХО..

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

Что касается # 1, у меня есть строго типизированный основной вид, который обладает свойством доступа к любому объекту сеанса represents....in мой экземпляр строго типизированного основного вида является универсальным, что дает мне некоторую гибкость в отношении строго типизированных страниц просмотра

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

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

а потом...

ViewPage<AdminViewModel<U>>

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

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

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

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

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

  2. Ты можешь издеваться HttpContextBase

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

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

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

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

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

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

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

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

Вот несколько примеров реализации ниже из интереса.

Используя этот метод, вы могли бы создать класс provider следующим образом:

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());
    }

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

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; }
        }

    }
}

Вы можете использовать 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  }); 

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top