2009-08-06 15 views
5

Digamos que tengo una aplicación web implementada como un conjunto de páginas de asistente para editar un objeto complejo. Hasta que el usuario hace clic en el botón "Finalizar", el objeto no quede guardado en el sistema back-end (un requisito), así que mientras tanto tengo que mantener a toda la información sobre el objeto en una especie de estado de sesión .ASP.NET MVC: prácticas recomendadas para mantener el estado de la sesión en una aplicación tipo asistente

Además, algunas de las páginas del asistente deben mostrar combo y cuadros de lista con una cantidad potencialmente grande de elementos. Estos elementos se obtienen del sistema de fondo utilizando un servicio web.

Coincidentemente, el asistente permite al usuario saltar libremente de una página de asistente a otra (usando vínculos de pestaña en la parte superior del formulario), así que no es una simple cosa "siguiente, siguiente ... terminar".

Restricción adicional: la aplicación web se ejecuta en una granja de servidores web y el cliente está cansado de usar el estado de sesión del lado del servidor. En el mejor de los casos quieren mantener el tamaño del estado de la sesión mínima (que tenían problemas con esto en el pasado).

Así que, básicamente hay dos problemas aquí:

  1. Cómo/dónde guardar los datos introducidos por el usuario en el Asistente?
  2. Ya sea para almacenar en caché los elementos combinados/lista recibida desde el back-end y si es así, ¿dónde?

Opciones estoy considerando:

  1. Almacenamiento del objeto en un WebForms-como ViewState (serializando en la página HTML). Esto también incluiría los elementos del cuadro combinado. Obviamente, podría haber un problema con las páginas HTML convertirse aplicación muy grande y por lo tanto Web será lenta.

  2. Almacenamiento en del lado del servidor de estado de sesión, independientemente de los deseos del cliente y sin saber cómo se verá afectado el rendimiento hasta que se prueba en el conjunto de servidores Web real (tarde en el proyecto).

no puedo decidir entre los dos. ¿O hay otra alternativa?

+2

Si baja la ruta de estado de la sesión, cree una carpeta de modelo personalizada y pase el objeto a los métodos de acción del controlador. – RichardOD

+0

Eso es con lo que ahora estoy jugando. De hecho, estoy pensando en usar el mismo modelo que el modelo de vista y luego serializarlo en el código de vista. Y luego deserializarlo utilizando una carpeta modelo. ¿Tiene sentido? –

Respuesta

5

¿Por qué caché? Se podía tener las páginas con pestañas donde cada página es un div o panel y mostrar sólo el div actual relacionada con su ficha. De esa manera usted no tiene que realizar un seguimiento y procesar todas las entradas cuando el usuario envía el formulario.

+0

Esa es ciertamente una opción y una pragmática. Supongo que la desventaja principal es el tiempo de descarga de la página inicial. Esto puede o no ser un problema, y ​​en el lado positivo, las transiciones del asistente serán instantáneas. – RichardOD

+1

OK, olvidé mencionar que hay mucha validación del lado del servidor involucrada. Ejemplo: cada vez que el usuario presiona el botón "Siguiente". Entonces, si todo se implementa como una sola página, entonces supongo que tendré que recurrir a la validación con AJAX, lo que complica mucho el diseño en mi caso. Pero es una alternativa válida, lo admito. –

2

Como dijo Daisy, no tiene que almacenarse en caché. También podría usar campos de formulario ocultos. Debido a que estos podrían asignarse al mismo objeto en cada acción del controlador, podría construir progresivamente el objeto a través de páginas sucesivas.

//Here's a class we're going to use 
public class Person 
{ 
    public int Age {get;set;} 
    public string Name {get;set;} 

    public Person() 
    { 
    } 
} 

//Here's the controller 
public Controller PersonCreator 
{ 
    public ActionResult CreatePerson() 
    { 
    //Posting from this page will go to SetPersonAge, as the name will be set in here. 
    return View(); 
    } 

    public ActionResult SetPersonAge(Person person) 
    { 
    //This should now have the name and age of the person 
    return View(person); 
    } 
} 

//Here is your SetPersonAge, which contains the name in the model already: 
<%= Html.Hidden("Name", Model.Name) %> 
<%Html.TextBox("Age") %> 

Y eso es todo.

+0

Yeap: otra opción válida. – RichardOD

+1

De hecho, mi diseño actual funciona de esta manera. Pero el problema son los controles de usuario más complejos, que son difíciles de mapear en el modo "oculto" de la misma manera que en el modo "visible" (por ejemplo, una vista de árbol llena desde el back-end). Tarde o temprano tendrá que recurrir a algún tipo de estado de vista serializada para ellos si desea evitar volver a solicitar los datos desde el back-end. –

+0

¿Por qué son más difíciles de mapear? Su ejemplo de vista en árbol no sería un problema. Y no estoy de acuerdo con su evaluación de que terminará necesitando algún tipo de viewstate serializado. Me parece que no ha visto por completo los beneficios de MVC y está tratando de encontrar soluciones que se ajusten más a los formularios web. –

3

¿Es posible almacenar los datos del asistente en una tabla temporal en la base de datos? Cuando el usuario finaliza el asistente, los datos se copian de la tabla temporal y se eliminan. La tabla temporal incluye una marca de tiempo para eliminar cualquier dato antiguo sin completar.

+0

¿Quizás como un LOB serializado? – RichardOD

+0

Desafortunadamente, la base de datos no es una opción para esto. –

1

puedo sugerir algunas opciones más

  1. Tener todo el asistente como una sola página con las lengüetas de mostrar y ocultar el contenido a través de JavaScript en el lado del cliente. Sin embargo, esto puede causar que la página inicial cargue más despacio.

  2. Almacenamiento en caché de los datos en el servidor utilizando el bloque de aplicación de almacenamiento en caché (o algo similar). Esto permitirá que todos los usuarios compartan una sola instancia de estos datos en lugar de duplicar en todas las sesiones. Ahora que los datos son más claros, es posible que pueda convencer al cliente para que permita el almacenamiento en la sesión.

+0

No estoy seguro de lo que quiere decir con 2. No sé por qué querría usar el bloque de aplicación de almacenamiento en caché en una aplicación web, cuando ASP.NET ya tiene un caché perfectamente aceptable. Sin embargo, +1 para el asistente del lado del cliente. – RichardOD

+0

@sabri, es una granja de servidores web y no puedo saber cómo se comportaría el almacenamiento en caché en esa configuración. Sería arriesgado para mí suponer que estará bien y no puedo probarlo lo suficientemente temprano. En cuanto a 1), mira mi respuesta a Daisy. –

+1

@RichardOD, Mi error. Estás en lo correcto; no hay necesidad de bloquear la aplicación de almacenamiento en caché y el objeto Caché sería mucho mejor. –

0

que he estado tratando con el mismo tema y, mientras mis requisitos son un poco más simple (Mantenimiento del Estado por sólo unos cuantos hilos), mi solución puede funcionar para usted. También me interesaría escuchar los pensamientos de otros sobre este enfoque.

Lo que terminé haciendo es: en el controlador, simplemente vuelco los datos que quiero en la propiedad Session del Controlador y luego los saco la próxima vez que lo necesite. Algo como esto para su situación:

//Here's the controller 
public Controller PersonCreator 
{ 
    public ActionResult CreatePerson() 
    {  
     //get the age out of the session 
     int age = (int)(Session["age"]); 
     //do something with it... 
     return View(); 
    } 
    public ActionResult SetPersonAge(Person person) 
    { 
     //put the age in the session 
     Session.Add("age", person.Age); 
     return View(person); 
    } 
} 

Lo que me gusta de esto es que no tengo que poner un montón de params ocultos alrededor en mis páginas de vista.

+0

Si bien eso sí funciona, obviamente es un ejemplo que necesita tener una clase abstracta/interfaz/global.asax/manejo de errores/mejores patrones y prácticas .... Pero sí que funciona. –

1

Hay una gran resistencia en la comunidad MVC contra el uso de sesiones. Los problemas son que muchos de nosotros los desarrolladores estamos construyendo sistemas de inicio de sesión como un sitio web bancario. Uno podría abogar por campos ocultos y eso funciona en algunas situaciones, pero cuando necesitamos programar a un usuario para la seguridad y el cumplimiento, entonces tiene varias opciones. Las cookies no son confiables. Confiar en los temporizadores de Javascript no son confiables y no son 508 compatibles, ya que el objetivo debería ser degradar con elegancia. Por lo tanto, para un inicio de sesión, una sesión es una buena opción. Si escribe la hora en el navegador del cliente, en la base de datos del servidor o en el sistema de archivos del servidor, igual debe administrar el tiempo por usuario.

Por lo tanto, utilice Sesiones con moderación, pero no las tema. Para los asistentes, técnicamente puedes serializar los campos ocultos pasándolos. Sospecho que la necesidad y el alcance serán mucho mayores y una implementación de autorización/autenticación con Sessions será la clave de la aplicación.

1

Si no puede usar ajax (para la validación & desplegables y capacidad de convertir el asistente a la página con pestañas) y no puede usar html5 (para almacenamiento en caché y almacenamiento de estado en almacenamiento local), entonces creo que está bastante disponible " mejores prácticas "y debe recurrir a uno malo (o peor).

Dado que MVC se opone a WebForms con respecto al uso de la sesión, ¿puede utilizar una solución alternativa? Por ejemplo, además de almacenar todos estos valores en algunos registros temporales de la base de datos que necesita limpiar más adelante, puede configurar AppFabric extension para Windows Server y usarlo para almacenar elementos de la lista desplegable (y el alcance puede ser para todos los usuarios, de modo que si hay más usuarios) usando el sistema al mismo tiempo, solo necesita una llamada al servicio web para actualizar el caché), y también para almacenar temporalmente sus objetos entre los pasos. Puede configurar sus objetos temporales en AppFabric para que caduquen automáticamente, por lo que no es necesario realizar una limpieza. También puede ser útil para acelerar otras partes de su sistema si llama extensamente a otro sistema a través de servicios web.

+0

Veo ahora que la pregunta tiene 2 años, por lo que la respuesta es irrelevante ahora, y sería irrelevante luego de que AppFabric se introdujera un año después :) –

+0

+1 sin embargo;) –

0

La respuesta a esto se puede encontrar en Steve Sanderson's ASP.NET MVC 2/3, y requiere una referencia al ensamblado de MVC Futures. Este enlace al Google Books es exactamente lo que hace.

En esencia, serializa los datos del asistente a la Vista. Un campo oculto se representa almacenando toda la información adquirida.

Su controlador puede decidir qué hacer mediante el uso de OnActionExecuting y OnResultExecuted (para atender las redirecciones) para pasarlo a la siguiente vista.

Haga que lea, lo explica con más detalle que yo.

Cuestiones relacionadas