Como usar sessões em um aplicativo ASP.NET MVC 4?

113

Eu sou novo no ASP.NET MVC. Já usei PHP antes e foi fácil criar uma sessão e selecionar registros de usuário com base nas variáveis ​​de sessão atuais.

Procurei em todos os lugares na Internet um tutorial simples passo a passo que pode me mostrar como criar e usar sessões em meu aplicativo C # ASP.NET MVC 4. Quero criar uma sessão com variáveis ​​de usuário que posso acessar de qualquer lugar em meus controladores e ser capaz de usar as variáveis ​​em minhas consultas LINQ.

Thuto Paul Gaotingwe
fonte
2
possível duplicata de Como manter a sessão de usuário com ASP.NET MVC
adatapost
2
Este artigo pode ser de seu interesse: brockallen.com/2012/04/07/think-twice-about-using-session-state
Daniel Hollinrake

Respostas:

160

Experimentar

//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;
Jobert Enamno
fonte
3
Obrigado Jobert! vc me deu uma ideia! apenas pensando no entanto .., é possível adicionar variáveis ​​de usuário a uma sessão durante o login? e também terei acesso a variáveis ​​de sessão (criadas apenas uma vez) em diferentes controladores em meu aplicativo?
Thuto Paul Gaotingwe
31
Você pode armazenar qualquer coisa ou qualquer dado de qualquer tipo em uma sessão. Depois de criado, você pode acessar o valor armazenado nele em todas as visualizações e controladores. Observe também que a sessão criada só pode ser acessada por usuário e por navegador. Significa que a sessão criada pelo Usuário1 usando o Firefox não pode ser acessada pelo mesmo usuário usando o IE. Também há coisas que você não deve fazer com a sessão, como. NÃO armazene muitos dados nele. Isso pode diminuir o desempenho do seu servidor. Por último, NÃO armazene dados confidenciais em uma sessão, como senha ou número de cartão de crédito
Jobert Enamno
2
Obrigado mais uma vez! Onde posso criá-lo para poder acessá-lo em diferentes controladores?
Thuto Paul Gaotingwe
2
@JobertEnamno é seguro armazenar o valor que vem de WebSecurity.CurrentUserIdmodo que não o retire do banco de dados várias vezes (descobri que é muito caro)?
Andrius Naruševičius
2
Não há sessão de controlador cruzado, portanto, quando você solicitar outro controlador, por exemplo de Account/LogOnpara Home/Index, Session["FirstName"]é null. Os desenvolvedores devem criar um controlador pai ( BaseController) e definir um campo protegido ( internal protected HttpSessionStateBase SharedSession) que pode expor a variável de sessão compartilhada em todos os subcontroladores (isso pressupõe que todos os controladores de seu aplicativo herdam de BaseController)
Bellash 09/09/2015
63

Devido à natureza sem estado da web, as sessões também são uma forma extremamente útil de persistir objetos em solicitações, serializando-os e armazenando-os em uma sessão.

Um caso de uso perfeito disso poderia ser se você precisar acessar informações regulares em seu aplicativo, para salvar chamadas de banco de dados adicionais em cada solicitação, esses dados podem ser armazenados em um objeto e não serializados em cada solicitação, assim:

Nosso objeto reutilizável e serializável:

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

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Caso de uso:

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

}

Uma vez que este objeto tenha sido serializado, podemos usá-lo em todos os controladores sem a necessidade de criá-lo ou consultar o banco de dados em busca dos dados contidos nele novamente.

Injetar seu objeto de sessão usando injeção de dependência

Em um mundo ideal, você iria " programar para uma interface, não para implementação " e injetar seu objeto de sessão serializável em seu controlador usando seu contêiner de Inversão de Controle de escolha, assim (este exemplo usa StructureMap, pois é o que estou mais familiarizado )

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

Você então registraria isso em seu Global.asax.csarquivo.

Para aqueles que não estão familiarizados com a injeção de objetos de sessão, você pode encontrar uma postagem de blog mais detalhada sobre o assunto aqui .

Uma palavra de alerta:

É importante notar que as sessões devem ser reduzidas ao mínimo, sessões grandes podem começar a causar problemas de desempenho.

Também é recomendado não armazenar nenhum dado sensível neles (senhas, etc).

Joseph Woodward
fonte
Onde você colocaria a definição de classe? Eu sou muito novo em tudo ainda, mas estou apenas curioso sobre como outros controladores verão a classe e saberão o que é. Você apenas adiciona no topo do controlador? Eu estava pensando em SessionStart em global.asax. Eu inicializaria coisas, mas talvez essa não seja a melhor maneira de fazer isso.
Shaun314
@ Shaun314 Idealmente, você usaria um contêiner IoC para injetar o objeto em seu controlador por meio de injeção de dependência (consulte a edição).
Joseph Woodward
1
Estou armazenando algumas informações da sessão após fazer o login do usuário usando a Identidade 2. Não consigo recuperar essas informações em outras ações e controladores além da primeira ação para a qual redireciono o usuário. Qualquer ideia?
Akbari
17

É assim que funciona o estado da sessão em ASP.NET e ASP.NET MVC:

Visão geral do estado da sessão ASP.NET

Basicamente, você faz isso para armazenar um valor no objeto Session:

Session["FirstName"] = FirstNameTextBox.Text;

Para recuperar o valor:

var firstName = Session["FirstName"];
Leniel Maccaferri
fonte
10
Não há sessão de controlador cruzado, portanto, quando você solicita outro controlador, por exemplo, de Accountpara Home, Sessão ["Nome"] é nulo. Os desenvolvedores devem criar um BaseControllere definir um campo protegido ( internal protected HttpSessionStateBase SharedSession) que pode expor a Sessionvariável compartilhada em todos os subcontroladores (isso pressupõe que todos os seus controladores de aplicativos herdam de BaseController)
Bellash
4
Umm, certo que existe? Há uma variável de sessão no controlador (o controlador de base fornecido pelo MVC).
aeliusd 01 de
7
@Bellash isso está completamente errado. As sessões estão disponíveis nos controladores. Acabei de definir Session ["test"] no HomeController e depois li no meu AccountController.
niico
0

Você pode armazenar qualquer tipo de dados em uma sessão usando:

Session["VariableName"]=value;

Essa variável vai durar 20 minutos ou mais.

Ulyses
fonte
-8

Você pode armazenar qualquer valor na sessão como Session ["FirstName"] = FirstNameTextBox.Text; mas vou sugerir que você tome um campo estático no modelo, atribua valor a ele e você possa acessar esse valor de campo em qualquer lugar do aplicativo. Você não precisa de sessão. sessão deve ser evitada.

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

no controlador - Employee.FullName = "ABC"; Agora você pode acessar este nome completo em qualquer lugar do aplicativo.

Mukul Sharma
fonte
10
Armazenar dados em campos estáticos, especialmente dados do usuário como o nome do funcionário, causará problemas graves em ambientes multiusuário. Quando dois usuários diferentes estiverem logados no sistema, eles verão o mesmo Employee.EmailAddress, pois o campo estático em Employee é o mesmo para cada instância.
Gökçer Gökdal