Jak korzystać z sesji w aplikacji ASP.NET MVC 4?

113

Jestem nowy w ASP.NET MVC. Wcześniej używałem PHP i łatwo było utworzyć sesję i wybrać rekordy użytkowników na podstawie aktualnych zmiennych sesji.

Szukałem wszędzie w Internecie prostego samouczka krok po kroku, który może pokazać mi, jak tworzyć i używać sesji w mojej aplikacji C # ASP.NET MVC 4. Chcę utworzyć sesję ze zmiennymi użytkownika, do których mam dostęp z dowolnego miejsca na moich kontrolerach i móc używać zmiennych w zapytaniach LINQ.

Thuto Paul Gaotingwe
źródło
2
możliwy duplikat How to
keep
2
Ten artykuł może być interesujące: brockallen.com/2012/04/07/think-twice-about-using-session-state
Daniel Hollinrake

Odpowiedzi:

160

Próbować

//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
źródło
3
Dzięki Jobert! Dałeś mi pomysł! zastanawiam się tylko… czy jest możliwe dodanie zmiennych użytkownika do sesji podczas logowania? a także czy będę miał dostęp do zmiennych sesji (utworzonych tylko raz) na różnych kontrolerach w mojej aplikacji?
Thuto Paul Gaotingwe,
31
W sesji możesz przechowywać wszystko lub dowolne dane dowolnego typu. Po utworzeniu możesz uzyskać dostęp do przechowywanej wartości we wszystkich widokach i kontrolerach. Zwróć również uwagę, że utworzona sesja jest dostępna tylko dla użytkownika i przeglądarki. Oznacza to, że sesja utworzona przez Użytkownika1 przy użyciu przeglądarki Firefox nie może być dostępna dla tego samego użytkownika za pomocą IE. Są też rzeczy, których nie powinieneś robić podczas sesji, takie jak. NIE przechowuj na nim dużych danych. Może to spowolnić działanie serwera. Wreszcie NIE przechowuj poufnych danych w sesji, takich jak hasło lub numer karty kredytowej
Jobert Enamno
2
Jeszcze raz dziękuję! Gdzie mogę go utworzyć, aby mieć do niego dostęp na różnych kontrolerach?
Thuto Paul Gaotingwe
2
@JobertEnamno czy można bezpiecznie przechowywać wartość, z której pochodzi, WebSecurity.CurrentUserIdaby nie pobierać jej wielokrotnie z bazy danych (stwierdziłem, że jest to bardzo kosztowne)?
Andrius Naruševičius
2
Nie ma sesji między kontrolerami, więc gdy zażądasz innego administratora, na przykład od Account/LogOndo Home/Index, Session["FirstName"]jest null. Programiści muszą utworzyć kontroler nadrzędny ( BaseController) i zdefiniować chronione pole ( internal protected HttpSessionStateBase SharedSession), które może ujawnić współdzieloną zmienną sesji we wszystkich kontrolerach podrzędnych (przy założeniu, że wszystkie kontrolery aplikacji dziedziczą po BaseController)
Bellash
63

Ze względu na bezstanowy charakter sieci, sesje są również niezwykle użytecznym sposobem utrwalania obiektów w żądaniach poprzez ich serializację i przechowywanie w sesji.

Idealnym przypadkiem użycia może być to, że potrzebujesz dostępu do regularnych informacji w całej aplikacji, aby zapisać dodatkowe wywołania bazy danych przy każdym żądaniu, dane te mogą być przechowywane w obiekcie i nieserializowane przy każdym żądaniu, na przykład:

Nasz obiekt wielokrotnego użytku, możliwy do serializacji:

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

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Przypadek użycia:

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

}

Po zserializowaniu tego obiektu możemy go używać na wszystkich kontrolerach bez konieczności tworzenia go lub ponownego wyszukiwania w bazie danych zawartych w nim danych.

Wstrzyknij obiekt sesji za pomocą Dependency Injection

W idealnym świecie `` zaprogramowałbyś interfejs, a nie implementację '' i wstrzyknął swój serializowalny obiekt sesji do kontrolera przy użyciu wybranego kontenera Inversion of Control (w tym przykładzie zastosowano StructureMap, ponieważ jest to ten, który najlepiej znam ).

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

Następnie zarejestrujesz to w swoim Global.asax.cspliku.

Dla tych, którzy nie są zaznajomieni z wstrzykiwaniem obiektów sesji, możesz znaleźć bardziej szczegółowy wpis na blogu na ten temat tutaj .

Słowo ostrzeżenia:

Warto zauważyć, że sesje powinny być ograniczone do minimum, duże sesje mogą zacząć powodować problemy z wydajnością.

Zaleca się również, aby nie przechowywać w nich żadnych wrażliwych danych (haseł itp.).

Joseph Woodward
źródło
Gdzie jednak umieściłbyś definicję klasy? Wciąż jestem całkiem nowy we wszystkim, ale jestem po prostu ciekawy, jak inni kontrolerzy zobaczą tę klasę i dowiedzą się, co to jest. Czy po prostu dodajesz go na górze kontrolera? Myślałem o SessionStart w global.asax. Zainicjowałbym rzeczy, ale może to nie jest najlepszy sposób na zrobienie tego.
Shaun314
@ Shaun314 Idealnie byłoby użyć kontenera IoC do wstrzyknięcia obiektu do kontrolera poprzez wstrzykiwanie zależności (patrz edycja).
Joseph Woodward,
1
Przechowuję niektóre informacje o sesji po zalogowaniu się użytkownika przy użyciu tożsamości 2. Nie jestem w stanie pobrać tych informacji w innych akcjach i kontrolerach poza pierwszą akcją, do której przekierowuję użytkownika. Dowolny pomysł?
Akbari
17

Oto jak działa stan sesji w ASP.NET i ASP.NET MVC:

Omówienie stanu sesji ASP.NET

Zasadniczo robisz to, aby zapisać wartość w obiekcie Session:

Session["FirstName"] = FirstNameTextBox.Text;

Aby pobrać wartość:

var firstName = Session["FirstName"];
Leniel Maccaferri
źródło
10
Nie ma sesji między kontrolerami, więc gdy żądasz innego kontrolera, na przykład od Accountdo Home, sesja ["FirstName"] ma wartość null. Programiści muszą utworzyć BaseControlleri zdefiniować chronione pole ( internal protected HttpSessionStateBase SharedSession), które może ujawniać wspólną Sessionzmienną we wszystkich kontrolerach podrzędnych (przy założeniu, że wszystkie kontrolery aplikacji dziedziczą po BaseController)
Bellash
4
Umm, na pewno jest? W kontrolerze (podstawowym kontrolerze dostarczonym przez MVC) znajduje się zmienna sesji.
aeliusd
7
@Bellash, to jest całkowicie błędne. Sesje są dostępne na różnych kontrolerach. Po prostu ustawiam sesję ["test"] w HomeController, a następnie czytam to w moim AccountController.
niico,
0

Możesz przechowywać dowolne dane w sesji za pomocą:

Session["VariableName"]=value;

Ta zmienna będzie trwać około 20 minut.

Ulyses
źródło
-8

U może przechowywać dowolną wartość w sesji, na przykład Session ["FirstName"] = FirstNameTextBox.Text; ale zasugeruję, abyś wziął jako pole statyczne w modelu przypisując mu wartość i możesz uzyskać dostęp do tej wartości pola w dowolnym miejscu w aplikacji. Nie potrzebujesz sesji. należy unikać sesji.

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

na kontrolerze - Employee.FullName = "ABC"; Teraz możesz uzyskać dostęp do tej pełnej nazwy w dowolnym miejscu aplikacji.

Mukul Sharma
źródło
10
Przechowywanie danych w polach statycznych, zwłaszcza danych użytkownika, takich jak nazwisko pracownika, spowoduje poważne problemy w środowiskach wielu użytkowników. Gdy dwóch różnych użytkowników zaloguje się do systemu, zobaczą ten sam adres Employee.Email, ponieważ pole statyczne w polu Employee jest takie samo dla każdej instancji.
Gökçer Gökdal