Când să folosiți TempData vs Session în ASP.Net MVC (Programare, Asp.Net Mvc, Sesiune, Tempdata)

scottm a intrebat.
a intrebat.

Încerc să mă obișnuiesc cu cadrul MVC, așa că aveți răbdare cu mine.

În acest moment, singurul lucru pentru care folosesc magazinul de sesiune este stocarea utilizatorului curent conectat. Site-ul meu este simplu. Pentru acest exemplu, ia în considerare trei obiecte de domeniu, Person, Meeting și File. Utilizatorii se pot autentifica și pot vizualiza un profil „doar pentru membri” al unei întâlniri și pot adăuga fișiere la aceasta, sau pot vizualiza „profilul” public al unei întâlniri dacă nu sunt autentificați.

Astfel, din profilul privat al reuniunii, cu un utilizator conectat, am un link „add files” (adaugă fișiere). Acest link este direcționat către FileContoller.Add(int meetingId). Din această acțiune, obțin reuniunea la care utilizatorul dorește să adauge fișiere folosind ID-ul reuniunii, dar după ce formularul este postat, trebuie să știu în continuare la ce reuniune adaugă fișiere utilizatorul. Aici se află întrebarea mea: ar trebui să trec întâlnirea „cu care interacționez în prezent” prin TempData sau să o adaug la magazinul Session?

Acesta este modul în care am configurat în prezent acțiunea de adăugare, dar nu funcționează:

    public ActionResult Add(int meetingId)
    {
        try
        {
            var meeting = _meetingsRepository.GetById(meetingId);
            ViewData.Model = meeting;
            TempData[TempDataKeys.CurrentMeeting] = meeting; /* add to tempdata here */
        }
        catch (Exception)
        {
            TempData[TempDataKeys.ErrorMessage] = "Unable to add files to this meeting.";
            return RedirectToRoute("MeetingsIndex");
        }

        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Add(FormCollection form)
    {
        var member = Session[SessionStateKeys.Member] as Member;
        var meeting = TempData[TempDataKeys.CurrentMeeting] as Meeting; /* meeting ends up null here */

        if (member == null)
        {
            TempData[TempDataKeys.ErrorMessage] = "You must be logged in to add files to an meeting.";
            return RedirectToRoute("LoginPage");
        }

        if (meeting == null) 
        {
            TempData[TempDataKeys.ErrorMessage] = "An error occurred. No meeting selected.";
            return RedirectToRoute("MeetingsIndex");
        }

            // add files to meeting

        TempData[TempDataKeys.Notification] = "Successfully added.";
        return RedirectToRoute("AddFiles", new {meetingId = meeting.MeetingId});
}

Editare:

Pe baza majorității răspunsurilor, poate cineva să ofere exemple cu privire la ce fel de date (altele decât mesajele) ar trebui stocate în TempData vs. Session?

Comentarii

  • Ce tip este TempDataKeys, doar o clasă? Sau un enum? –  > Por Anon343224user.
  • @Anon343224user este prea târziu, dar scriu pentru cine se întreabă ca tine și ca mine. M-am întrebat și eu și am găsit o utilizare similară la github.com/Macht59/StenoCryptor/blob/master/… este o clasă statică și conține câmpuri consts string. –  > Por Furkan Ekinci.
  • Notă pentru cititorii moderni: TempData funcționează diferit începând cu .NET Core față de modul în care este descris în multe dintre răspunsurile de aici. Consultați răspunsul meu de aici pentru detalii. –  > Por MarredCheese.
7 răspunsuri
Craig Stuntz

TempData este sesiune, deci nu sunt complet diferite. Cu toate acestea, distincția este ușor de înțeles, deoarece TempData este pentru redirecționări, și numai pentru redirecționări. Deci, atunci când setați un anumit mesaj în TempData și apoi redirecționați, utilizați TempData corect.

Cu toate acestea, utilizarea Session pentru orice fel de securitate este extrem de periculoasă. Session și Membership sunt complet separate în ASP.NET. Puteți „fura” sesiuni de la alți utilizatori, și da, oamenii atacă site-urile web în acest mod. Deci, dacă doriți să opriți selectiv o informație de postare pe baza faptului că un utilizator este conectat, uitați-vă la IsAuthenticated, iar dacă vreți să afișați selectiv informații în funcție de tipul de utilizator conectat, folosiți o funcție Furnizor de roluri. Deoarece GET-urile pot fi stocate în memoria cache, se poate utiliza numai mod de a permite accesul selectiv la o acțiune într-un GET este cu AuthorizeAttribute.

Actualizare Ca răspuns la întrebarea dvs. editată: Aveți deja un exemplu bun de utilizare a TempData în întrebarea dumneavoastră, și anume, returnarea unui mesaj de eroare simplu după un POST eșuat. În ceea ce privește ceea ce ar trebui să fi stocate în Session (dincolo de „nu prea multe”), mă gândesc la Session ca la o memorie cache specifică utilizatorului. La fel ca și Cache-ul nespecific utilizatorului, nu ar trebui să puneți acolo informații sensibile din punct de vedere al securității. Dar este un loc bun pentru a pune chestii care sunt relativ costisitoare pentru căutare. De exemplu, în Site.Master al nostru este afișat numele complet al utilizatorului. Acesta este stocat într-o bază de date și nu dorim să facem o interogare a bazei de date pentru el la fiecare pagină pe care o servim. (O instalare a aplicației noastre este utilizată într-o singură companie, astfel încât numele complet al unui utilizator nu este considerat „sensibil din punct de vedere al securității”). Așadar, dacă vă gândiți la Session ca la o memorie cache care variază în funcție de un cookie pe care îl are utilizatorul, nu veți greși prea mult.

Comentarii

  • Nu am nevoie de roluri, toată lumea are același acces odată logat. Totuși, mă voi documenta cu privire la IsAuthenticated, mulțumesc.  > Por scottm.
  • Mecanismul de autentificare nu se bazează pe cookie și nu poate fi furat în mod similar? –  > Por IsmailS.
  • @Ismail, da, este implicat un cookie (în mod implicit). Nu, nu poate fi furat într-un mod similar. Autentificarea este concepută pentru a fi sigură. Sesiunea nu este. Sunt două lucruri diferite. –  > Por Craig Stuntz.
  • @CraigStuntz Mulțumesc pentru explicație, Dar cum rămâne cu performanța! Folosirea sesiunii este încetinește timpul de încărcare a aplicației? –  > Por Abdulsalam Elsharif.
  • @AbdulsalamElsharif Da, utilizarea sesiunii afectează puțin performanța. Dar probabil că va trebui să dezactivați în totalitate Session pentru controler (nu doar să evitați TempData) pentru a evita acest lucru. –  > Por Craig Stuntz.
tvanfosson

Furnizorul TempData implicit utilizează sesiunea, astfel încât nu există cu adevărat o mare diferență, cu excepția faptului că TempData este șters la sfârșitul următoarei cereri. Ar trebui să folosiți TempData atunci când datele trebuie să persiste doar între două cereri, de preferință a doua fiind o redirecționare pentru a evita problemele legate de alte cereri ale utilizatorului – de exemplu, de la AJAX – care șterg accidental datele. În cazul în care datele trebuie să persiste mai mult decât atât, ar trebui fie să repopulați TempData, fie să utilizați direct Session.

Comentarii

  • Înțeleg asta. Am pus obiectul întâlnirii în TempData în metoda GET, apoi, când utilizatorul postează formularul, ar trebui să îl pot prelua din nou din TempData, nu? –  > Por scottm.
  • Nu, nu se poate număra. TempData este doar pentru redirecționare. Dacă setați TempData într-o metodă GET, apoi pagina dvs. face un apel AJAX, apoi utilizatorul postează, TempData este dispărut. –  > Por Craig Stuntz.
  • „Nu, nu puteți număra.” -> „”Nu, nu poți conta pe asta”. Vedeți linkul din răspunsul meu pentru mai multe informații despre TempData și redirecționări. –  > Por Craig Stuntz.
  • @Craig, înțeleg ce vrei să spui. Dacă nu fac nicio cerere ajax, nu ar trebui să fie tot acolo, în cazul meu? –  > Por scottm.
  • Nu aș paria pe asta. Ce se întâmplă dacă utilizatorul postează datele, dar nu reușește, din cauza validării pe server. Deci, POST-ul returnează o vizualizare, în loc să redirecționeze. Utilizatorul rezolvă problema validării și face din nou POST. Datele temporare nu mai există, deoarece au fost șterse după eșecul POST. Oricum, probabil că veți folosi AJAX mai devreme sau mai târziu, așa că nu vă faceți planuri pentru a nu-l folosi. TempData este într-adevăr doar pentru redirecționări; acest lucru mi-a fost confirmat în privat de către un membru al echipei MVC. –  > Por Craig Stuntz.
A Coder

Îl puteți utiliza conform cerințelor dumneavoastră. O clarificare poate fi,

TempData Vs Sesiune

TempData

  1. TempData ne permite să persistăm datele pe durata unei singure cereri ulterioare.
  2. ASP.net MVC va expira în mod automat valoarea tempdata odată ce o cerere consecutivă a returnat rezultatul (ceea ce înseamnă că aceasta trăiește doar până când vizualizarea țintă este complet încărcată).
  3. Aceasta este valabilă numai pentru cererea curentă și pentru cererile ulterioare.
  4. TempData dispune de metoda Keep pentru a păstra valoarea TempData.

    Exemplu:

    TempData.Keep(), TempData.Keep(„EmpName”)

  5. TempData stochează în mod intern valoarea în variabila Session.

  6. Aceasta este utilizată pentru a stoca doar o singură dată mesaje precum mesajele de validare, mesajele de eroare etc.

Session:

  1. Sesiunea este capabilă să stocheze date mult mai mult timp, până când sesiunea utilizatorului nu expiră.
  2. Sesiunea va expira după ce sesiunea a expirat.
  3. Este valabilă pentru toate cererile.
  4. N/A
  5. Variabilele sesiunii sunt stocate în obiectul SessionStateItemCollection (care este expus prin intermediul proprietății HttpContext.Session a paginii).
  6. Acesta este utilizat pentru a stoca date de lungă durată, cum ar fi ID-ul utilizatorului, ID-ul rolului etc., care sunt necesare pe parcursul sesiunii utilizatorului.

Atât TempData, cât și sesiunea, necesită tipărire pentru obținerea datelor și verificarea valorilor nule pentru a evita excepțiile în timpul execuției.

Comentarii

  • Acesta este un răspuns foarte util, deoarece ne ajută să decidem foarte clar când să folosim ce anume. –  > Por Marcel.
womp

„Nu funcționează” nu este foarte descriptiv, dar permiteți-mi să vă ofer câteva sugestii.

Sub capotă, TempData folosește Session pentru a stoca valorile. Deci nu există o mare diferență în ceea ce privește mecanismele de stocare sau ceva de genul acesta. Cu toate acestea, TempData durează doar până la primirea următoarei cereri.

Dacă utilizatorul face o solicitare ajax între postările din formular, TempData dispare. Orice solicitare, oricare ar fi ea, va șterge TempData. Deci, este într-adevăr de încredere doar atunci când faceți o redirecționare manuală.

De ce nu puteți pur și simplu să redați ID-ul întâlnirii într-un câmp ascuns în formularul de vizualizare? Îl adăugați deja la model. Alternativ, adăugați-l la ruta dvs. ca parametru.

Comentarii

  • Există două comentarii care descriu ceea ce nu funcționează pentru mine. Am presupus că aș putea să trec obiectul și să nu mai fie nevoie să îl recuperez din nou din baza de date, dar acum că mă gândesc la asta, acest lucru ar adăuga probabil o mulțime de probleme de concurență. –  > Por scottm.
D’Arcy Rittich

Prefer să păstrez acest tip de date în pagina însăși. Redați meetingID ca o intrare ascunsă, astfel încât să fie trimisă înapoi la controler. Controlerul care se ocupă de postare poate apoi să transmită acel ID al întâlnirii înapoi la orice vizualizare care va fi redată, astfel încât meetingID este practic transmis cât timp aveți nevoie de el.

Este un fel de diferență între a stoca o valoare într-o variabilă globală înainte de a apela o metodă care va opera asupra ei și a transmite valoarea direct metodei.

regina3

Aș sugera soluția lui MvcContrib:http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/

Dacă nu doriți MvcContrib complet, soluția este doar 1 metodă + 1 clasă pe care o puteți lua cu ușurință din sursele MvcContrib.

Mervin

Valoarea proprietății TempData este stocată în starea sesiunii. Valoarea lui TempData persistă până când este citită sau până când sesiunea se termină. Dacă doriți să transmiteți date de la o vizualizare a controlerului la o altă vizualizare a controlerului, atunci ar trebui să utilizați TempData.

Utilizați Session atunci când datele sunt necesare pentru întreaga aplicație