【问题标题】:How to use sessions in an ASP.NET MVC 4 application?如何在 ASP.NET MVC 4 应用程序中使用会话?
【发布时间】:2012-12-17 19:30:55
【问题描述】:

我是 ASP.NET MVC 的新手。我以前使用过 PHP,很容易创建会话并根据当前会话变量选择用户记录。

我在 Internet 上到处寻找一个简单的分步教程,它可以向我展示如何在我的 C# ASP.NET MVC 4 应用程序中创建和使用会话。我想创建一个包含用户变量的会话,我可以从控制器中的任何位置访问该会话,并能够在我的 LINQ 查询中使用这些变量。

【问题讨论】:

标签: asp.net-mvc session asp.net-mvc-4 session-variables


【解决方案1】:

您可以使用以下方法在会话中存储任何类型的数据:

Session["VariableName"]=value;

这个变量会持续 20 分钟左右。

【讨论】:

    【解决方案2】:

    由于 Web 的无状态特性,会话也是一种非常有用的方法,可以通过序列化对象并将它们存储在会话中来跨请求持久化对象。

    一个完美的用例可能是,如果您需要在整个应用程序中访问常规信息,以便在每个请求上保存额外的数据库调用,这些数据可以存储在一个对象中并在每个请求上反序列化,如下所示:

    我们的可重用、可序列化对象:

    [Serializable]
    public class UserProfileSessionData
    {
        public int UserId { get; set; }
    
        public string EmailAddress { get; set; }
    
        public string FullName { get; set; }
    }
    

    用例:

    public class LoginController : Controller {
    
        [HttpPost]
        public ActionResult Login(LoginModel model)
        {
            if (ModelState.IsValid)
            {
                var profileData = new UserProfileSessionData {
                    UserId = model.UserId,
                    EmailAddress = model.EmailAddress,
                    FullName = model.FullName
                }
    
                this.Session["UserProfile"] = profileData;
            }
        }
    
        public ActionResult LoggedInStatusMessage()
        {
            var profileData = this.Session["UserProfile"] as UserProfileSessionData;
    
            /* From here you could output profileData.FullName to a view and
            save yourself unnecessary database calls */
        }
    
    }
    

    一旦这个对象被序列化,我们就可以在所有控制器中使用它,而无需再次创建它或查询数据库以获取其中包含的数据。

    使用依赖注入注入会话对象

    在一个理想的世界中,你会'program to an interface, not implementation'并使用你选择的控制反转容器将你的可序列化会话对象注入你的控制器,就像这样(这个例子使用了我最熟悉的结构映射) .

    public class WebsiteRegistry : Registry
    {
        public WebsiteRegistry()
        {
            this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());   
        }
    
        public static IUserProfileSessionData GetUserProfileFromSession()
        {
            var session = HttpContext.Current.Session;
            if (session["UserProfile"] != null)
            {
                return session["UserProfile"] as IUserProfileSessionData;
            }
    
            /* Create new empty session object */
            session["UserProfile"] = new UserProfileSessionData();
    
            return session["UserProfile"] as IUserProfileSessionData;
        }
    }
    

    然后您将在您的 Global.asax.cs 文件中注册它。

    对于不熟悉注入会话对象的人,您可以找到关于主题here 的更深入的博客文章。

    一句警告:

    值得注意的是,会话应保持在最低限度,大型会话可能会开始导致性能问题。

    还建议不要在其中存储任何敏感数据(密码等)。

    【讨论】:

    • 你会把类定义放在哪里呢?我对一切仍然很陌生,但我只是好奇其他控制器将如何看到该类并知道它是什么。你只是将它添加到控制器的顶部吗?我正在考虑 global.asax 中的 SessionStart 我会初始化一些东西,但也许这不是最好的方法。
    • @Shaun314 理想情况下,您会使用 IoC 容器通过依赖注入将对象注入您的控制器(请参阅编辑)。
    • 我在使用身份 2 登录用户后存储了一些会话信息。除了我将用户重定向到的第一个操作之外,我无法在其他操作和控制器中检索这些信息。有什么想法吗?
    【解决方案3】:

    U 可以在会话中存储任何值,例如 会话["FirstName"] = FirstNameTextBox.Text; 但我建议您将模型中的静态字段作为为其分配值,您可以在应用程序中的任何位置访问该字段值。你不需要会话。应该避免会话。

    public class Employee
    {
       public int UserId { get; set; }
       public string EmailAddress { get; set; }
       public static string FullName { get; set; }
    }
    

    在控制器上 - Employee.FullName = "ABC"; 现在你可以在应用程序的任何地方访问这个全名了。

    【讨论】:

    • 在静态字段中存储数据,尤其是像员工姓名这样的用户数据,在多用户环境中会导致严重的问题。当两个不同的用户登录系统时,他们将看到相同的 Employee.EmailAddress,因为 Employee 上的静态字段对于每个实例都是相同的。
    【解决方案4】:

    试试

    //adding data to session
    //assuming the method below will return list of Products
    
    var products=Db.GetProducts();
    
    //Store the products to a session
    
    Session["products"]=products;
    
    //To get what you have stored to a session
    
    var products=Session["products"] as List<Product>;
    
    //to clear the session value
    
    Session["products"]=null;
    

    【讨论】:

    • 谢谢乔伯特!你给了我一个主意!只是想知道..,可以在登录期间将用户变量添加到会话中吗?我是否可以在我的应用程序中跨不同控制器访问会话变量(仅创建一次)?
    • 您可以在会话中存储任何内容或任何类型的任何数据。创建后,您可以在所有视图和控制器中访问存储在其中的值。另请注意,创建的会话只能按用户和浏览器访问。这意味着 User1 使用 Firefox 创建的会话不能由使用 IE 的同一用户访问。还有一些事情你不应该对会话做,例如。不要在上面存储大量数据。这可能会降低服务器的性能。最后,不要将敏感数据存储到会话中,例如密码或信用卡号
    • 再次感谢!我在哪里创建它才能跨不同的控制器访问它?
    • @JobertEnamno 存储来自WebSecurity.CurrentUserId 的值是否安全,因此它不会多次从数据库中提取它(我发现它非常昂贵)?
    • 没有跨控制器会话,因此当您请求另一个控制器时,例如从Account/LogOnHome/IndexSession["FirstName"]null。开发人员必须创建一个父控制器(BaseController)并定义一个受保护的字段(internal protected HttpSessionStateBase SharedSession),该字段可能会在所有子控制器中公开共享的 Session 变量(这假设您所有的应用程序控制器都继承自 BaseController)跨度>
    【解决方案5】:

    这就是会话状态在 ASP.NET 和 ASP.NET MVC 中的工作方式:

    ASP.NET Session State Overview

    基本上,您这样做是为了在 Session 对象中存储一个值:

    Session["FirstName"] = FirstNameTextBox.Text;
    

    要检索值:

    var firstName = Session["FirstName"];
    

    【讨论】:

    • 没有跨控制器会话,因此当您请求另一个控制器时,例如从AccountHome,Session["FirstName"] 为空。开发人员必须创建一个BaseController 并定义一个受保护的字段(internal protected HttpSessionStateBase SharedSession),该字段可能会在所有子控制器中公开共享的Session 变量(这假设您的所有应用程序控制器都继承自BaseController
    • 嗯,确定有? Controller(MVC提供的基本控制器)中有一个Session变量。
    • @Bellash 这是完全错误的。会话跨控制器可用我只是在 HomeController 中设置 Session["test"] 然后在我的 AccountController 中读取它。
    猜你喜欢
    • 2020-03-04
    • 1970-01-01
    • 2015-11-12
    • 2014-02-01
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    相关资源
    最近更新 更多