2009-09-30 21 views
57

Estoy tratando de entender el framework MVC así que tengan paciencia conmigo.Cuándo usar TempData vs Session en ASP.Net MVC

En este momento, lo único que estoy usando en el almacén de sesión es almacenar el usuario que está conectado actualmente. Mi sitio web es simple. Para este ejemplo, considere tres objetos de dominio, Persona, Reunión y Archivo. Los usuarios pueden iniciar sesión y ver el perfil de "solo miembros" de una reunión y agregarle archivos, o ver el "perfil" público de una reunión si no han iniciado sesión.

Por lo tanto, desde el perfil privado de la reunión, con un usuario conectado, tengo un enlace "agregar archivos". Este enlace se dirige a FileContoller.Add (int meetingId). A partir de esta acción, obtengo la reunión a la que el usuario desea agregar archivos usando la identificación de reunión, pero después de que se haya publicado el formulario, aún necesito saber a qué reunión está agregando archivos el usuario. Ahí radica mi pregunta, ¿debo aprobar la reunión "actualmente interactuando con" a través de TempData, o agregarla a la tienda de la sesión?

Esta es la forma en este momento tengo la configuración Agregar acción, pero que no está funcionando:

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

Editar:

Sobre la base de la mayoría de las respuestas, puede cualquiera dar ejemplos de ¿Qué tipo de datos (que no sean mensajes) deberían almacenarse en TempData vs Session?

+0

¿Qué tipo es TempDataKeys, solo una clase? ¿O una enumeración? – Anon343224user

Respuesta

83

TempData es una sesión, por lo que no son del todo diferentes. Sin embargo, la distinción es fácil de entender, porque TempData is for redirects, and redirects only. Entonces, cuando configura un mensaje en TempData y luego lo redirecciona, está utilizando TempData correctamente.

Sin embargo, usar Session para cualquier tipo de seguridad es extremadamente peligroso. La sesión y la membresía están completamente separadas en ASP.NET. You can "steal" sessions from other users, y sí, las personas atacan los sitios web de esta manera. Por lo tanto, si desea detener selectivamente una información de publicación según si un usuario inició sesión, consulte IsAuthenticated, y si desea mostrar selectivamente información según el tipo de usuario que haya iniciado sesión, use Role provider. Debido a que los GET se pueden almacenar en caché, el único forma de permitir el acceso selectivo a una acción en un GET es con AuthorizeAttribute.

Actualización En respuesta a su pregunta editada: Ya tiene un buen ejemplo del uso de TempData en su pregunta, es decir, devolver un mensaje de error simple después de una POST fallida. En términos de qué se debe almacenar en Session (más allá de "no mucho"), solo pienso en Session como un caché específico del usuario. Al igual que la caché no específica del usuario, no debe colocar allí información confidencial. Pero es un buen lugar para colocar cosas que es relativamente caro de buscar. Por ejemplo, nuestro Site.Master tiene el nombre completo del usuario que se muestra en él. Eso se almacena en una base de datos, y no queremos hacer una consulta de base de datos para cada página que servimos. (Una instalación de nuestra aplicación se usa en una sola compañía, por lo que el nombre completo de un usuario no se considera "sensible a la seguridad"). Por lo tanto, si considera que la Sesión es un caché que varía según la cookie que tiene el usuario, no ganó estar muy equivocado

+0

No necesito roles, todos tienen el mismo acceso una vez que inicie sesión. I w haré mi investigación en IsAuthenticated aunque, gracias – scottm

+1

¿El mecanismo de Autenticación no está basado en una cookie y no puede ser robado de manera similar? – IsmailS

+2

@Ismail, sí, una cookie está involucrada (de forma predeterminada). No, no puede ser robado de manera similar. La autenticación está diseñada para ser segura. La sesión no es. Son dos cosas diferentes. –

4

"No funciona" no es muy descriptivo, pero permítame ofrecerle algunas sugerencias.

Bajo el capó, TempData usa Session para almacenar valores. Entonces, no hay mucha diferencia en términos de mecanismos de almacenamiento o algo así. Sin embargo, TempData solo dura hasta que se reciba la siguiente solicitud.

Si el usuario realiza una solicitud de ajax entre publicaciones de formulario, TempData se va. Cualquier solicitud que borre TempData. Por lo tanto, solo es confiable cuando realizas una redirección manual.

¿Por qué no puedes simplemente presentar la ID de reunión en un campo oculto en tu formulario de visualización? Ya lo está agregando al modelo. Alternativamente, agréguelo a su ruta como un parámetro.

+0

Hay dos comentarios que describen lo que no funciona para mí. Supuse que podía pasar el objeto y no tener que recuperarlo de la base de datos nuevamente, pero ahora que lo pienso, eso probablemente agregaría muchos problemas de simultaneidad. – scottm

0

Prefiero mantener ese tipo de datos en la página. Render meetingID como una entrada oculta, por lo que se envía de vuelta al controlador. El controlador que maneja la publicación puede luego devolver esa Id. De reunión a la vista que se muestre, de modo que la ID de reunión básicamente se transfiera todo el tiempo que la necesite.

Es como la diferencia entre almacenar un valor en una variable global antes de llamar a un método que operará en él, o pasar el valor directamente al método.

16

El proveedor predeterminado de TempData utiliza la sesión por lo que realmente no hay mucha diferencia, excepto que su TempData se borra al final de la próxima solicitud. Debe usar TempData cuando los datos solo necesiten persistir entre dos solicitudes, preferiblemente la segunda es una redirección para evitar problemas con otras solicitudes del usuario, desde AJAX, por ejemplo, borrando los datos accidentalmente. Si los datos deben persistir durante más tiempo, debe volver a llenar el archivo TempData o usar la sesión directamente.

+1

Entiendo eso. Puse el objeto de reunión en TempData en el método GET, luego cuando los usuarios publican el formulario, debería poder recuperarlo de TempData nuevamente, ¿verdad? – scottm

+3

No, no puedes contar. TempData es solo para redirigir. Si configura TempData en un GET, su página realiza una llamada AJAX, luego los POST del usuario, el TempData * se ha ido. * –

+1

"No, no puede contar". -> "" No, no puedes contar con eso. "Ver el enlace en mi respuesta para más información sobre TempData y redirecciones. –

0

El valor de la propiedad TempData se almacena en estado de sesión. El valor de TempData persiste hasta que se lee o hasta que la sesión expira. Si desea pasar datos de una vista de controlador a otra vista de controlador, entonces debe usar TempData.

Uso Sesión cuando los datos es necesario para la aplicación en toda

3

Se puede utilizar como por su exigencia. Una aclaración puede ser,

TempData Vs Sesión

TempData

  1. TempData nos permiten a la persistencia de los datos para la duración de la solicitud posterior sola.
  2. ASP.net MVC caducará automáticamente el valor de tempdata una vez que la solicitud consecutiva haya devuelto el resultado (es decir, esté activo solo hasta que la vista de destino esté completamente cargada).
  3. Es válido solo para la solicitud actual y posterior
  4. TempData tiene el método Keep para conservar el valor de TempData.

    Ejemplo:

    TempData.Keep(), TempData.Keep (“EmpName”) almacena

  5. TempData internamente el valor en la Sesión variable.

  6. Se utiliza para mensajes sólo una vez almacenados como mensajes de validación, mensajes de error, etc.

Sesión:

  1. Sesión es capaz de almacenar datos mucho más largo tiempo, hasta que el usuario la sesión no expira
  2. La sesión caducará después de que se haya agotado el tiempo de espera de la sesión.
  3. Válido para todas las solicitudes.
  4. N/A
  5. La varible de sesión se almacena en el objeto SessionStateItemCollection (que se expone a través de la propiedad HttpContext.Session de la página).
  6. Se utiliza para almacenar datos de larga duración como ID de usuario, ID de rol, etc. que requirieron durante toda la sesión del usuario.

TempData y sesión, ambos requieren encasillamiento para obtener datos y verificar valores nulos para evitar la excepción de tiempo de ejecución.