如何在ASP.NET MVC 4应用程序中使用会话?


113

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

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



Answers:


160

尝试

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

3
谢谢乔伯特!你给我一个主意!只是想知道..,是否可以在登录期间向会话添加用户变量?我还能在应用程序中的不同控制器之间访问会话变量(仅创建一次)吗?
Thuto Paul Gaotingwe

31
您可以在会话中存储任何内容或任何类型的任何数据。创建后,您可以在所有视图和控制器之间访问存储在其中的值。另请注意,仅每个用户和每个浏览器都可以访问创建的会话。意味着同一用户使用IE无法访问User1使用Firefox创建的会话。还有一些您不应该使用会话的东西,例如。不要在上面存储大数据。这可能会降低服务器的性能。最后,不要将敏感数据存储到会话中,例如密码或信用卡号
Jobert Enamno 2013年

2
再次感谢!我在哪里创建它以便能够跨不同的控制器访问它?
Thuto Paul Gaotingwe

2
@JobertEnamno是否可以安全地存储来自其的值,WebSecurity.CurrentUserId这样它就不会多次从数据库中提取它(我发现它非常昂贵)?
AndriusNaruševičius2014年

2
没有跨控制器会话,因此当您请求另一个控制器(例如,从Account/LogOnto到Home/IndexSession["FirstName"]为时null。开发人员必须创建一个父控制器(BaseController)并定义一个受保护的字段(internal protected HttpSessionStateBase SharedSession),该字段可能会在所有子控制器中公开共享的Session变量(假设您的所有应用程序控制器都继承自BaseController
Bellash

63

由于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 */
    }

}

序列化此对象后,我们可以在所有控制器上使用它,而无需创建它或再次在数据库中查询其中包含的数据。

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

在理想情况下,您将“ 编程为接口,而不是实现 ”,并使用所选的Inversion of Control容器将可序列化的会话对象注入控制器中,如下所示(此示例使用StructureMap,因为它是我最熟悉的一个)。

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文件中注册它。

对于不熟悉注入会话对象的用户,您可以在此处找到有关该主题的更深入的博客文章。

警告:

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

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


但是,您将类定义放在哪里?我对所有事情还很陌生,但是我只是对其他控制器如何看待该类并知道它是什么感到好奇。您是否只是将其添加到控制器的顶部?我正在考虑在global.asax中使用SessionStart进行初始化,但这也许不是最好的方法。
Shaun314 2014年

@ Shaun314理想情况下,您将使用IoC容器通过依赖项注入将对象注入到控制器中(请参见编辑)。
约瑟夫·伍德沃德

1
使用Identity 2登录用户后,我将存储一些会话信息。除了将用户重定向到的第一个操作外,我无法在其他操作和控制器中检索这些信息。任何想法?
Akbari 2015年

17

会话状态在ASP.NET和ASP.NET MVC中的工作方式如下:

ASP.NET会话状态概述

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

Session["FirstName"] = FirstNameTextBox.Text;

要获取值:

var firstName = Session["FirstName"];

10
没有跨控制器会话,因此当您请求另一个控制器时,例如from AccountHome,Session [“ FirstName”]为空。开发人员必须创建一个,BaseController并定义一个受保护的字段(internal protected HttpSessionStateBase SharedSession),该字段可以Session在所有子控制器中公开共享变量(假设您的所有应用程序控制器都继承自BaseController
Bellash

4
嗯,确定有吗?Controller(MVC提供的基本控制器)中有一个Session变量。
aeliusd

7
@Bellash,这是完全错误的。我可以在HomeController中设置Session [“ test”],然后在AccountController中读取它,因此跨控制器的会话都是可用的。
niico

0

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

Session["VariableName"]=value;

该变量将持续20分钟左右。


-8

U可以在会话中存储任何值,例如Session [“ 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”; 现在,您可以在应用程序中的任何位置访问此全名。


10
在静态字段上存储数据,尤其是诸如雇员姓名之类的用户数据将在多用户环境中引起严重的问题。当两个不同的用户登录系统时,他们将看到相同的Employee.EmailAddress,因为Employee上的静态字段对于每个实例都是相同的。
GökçerGökdal
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.