首页 文章

ASP.NET MVC中的会话变量

提问于
浏览
164

我正在编写一个Web应用程序,允许用户浏览网站内的多个网页,提出某些请求 . 用户输入的所有信息都将存储在我创建的对象中 . 问题是我需要从网站的任何部分访问此对象,我真的不知道实现这一目标的最佳方法 . 我知道一个解决方案是使用会话变量,但我不知道如何在asp .net MVC中使用它们 . 我会在哪里声明会话变量?还有其他方法吗?

10 回答

  • 7

    我认为你会想到事情是否真的属于会话状态 . 这是我发现自己经常做的事情,这是一个很好的强类型方法,但是在把事情放在会话上下文时你应该小心 . 不是所有东西都应该只是因为它属于某个用户 .

    在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'
    }
    
  • 44

    答案在这里是正确的,但我努力在ASP.NET MVC 3应用程序中实现它 . 我想访问控制器中的Session对象,但无法弄清楚为什么我继续得到“实例未设置为Object错误的实例” . 我注意到在控制器中,当我尝试通过执行以下操作来访问会话时,我一直在收到该错误 . 这是因为this.HttpContext是Controller对象的一部分 .

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

    但是,我想要的是HttpContext,它是System.Web命名空间的一部分,因为这是上面建议在Global.asax.cs中使用的答案 . 所以我必须明确地做以下事情:

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

    这帮助了我,不确定我是否做了任何不是M.O.在这附近,但我希望它可以帮到某人!

  • 6

    因为我不喜欢看到关于这个地方的“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 .

    HTH

  • 14

    好吧,恕我直言..

    • 从不在视图/母版页中引用会话

    • 最小化您对Session的使用 . MVC为此提供了TempData obj,它基本上是一个用于单次访问服务器的Session .

    关于#1,我有一个强类型的主视图,它具有访问Session对象所代表的任何属性....在我的实例中,强大的主视图是通用的,这给了我一些关于强类型视图页面的灵活性

    ViewMasterPage<AdminViewModel>
    
    AdminViewModel
    {
        SomeImportantObjectThatWasInSession ImportantObject
    }
    
    AdminViewModel<TModel> : AdminViewModel where TModel : class
    {
       TModel Content
    }
    

    然后...

    ViewPage<AdminViewModel<U>>
    
  • 20

    虽然我不知道asp.net mvc,但这是我们应该在普通的.net网站上做的事情 . 它也适用于asp.net mvc .

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

    您可以将其放在方法中以便于访问 . HTH

  • 13

    有3种方法可以做到这一点 .

    你可以直接访问HttpContext.Current.Session你可以模拟HttpContextBase为HttpContextBase创建一个扩展方法

    我更喜欢第三种方式 . 这个链接很好参考 .

    Get/Set HttpContext Session Methods in BaseController vs Mocking HttpContextBase to create Get/Set methods

  • 7

    这些家伙给出了很好的答案,但我会提醒你不要总是依赖 Session . 这样做既快捷又容易,当然会起作用,但在所有的cicrumstances中都不会很好 .

    例如,如果您遇到托管不允许使用会话,或者您在Web场中或在共享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());
        }
    
  • 4

    您可以将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  });
    

    第二个参数是可选的,当会话中不存在值时,将使用该键填充该键的会话数据 .

  • 122

    我访问会话的方法是编写一个辅助类,它封装了各种字段名称及其类型 . 我希望这个例子有帮助:

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

相关问题