¿Hay alguna buena razón para usar FormCollection en lugar de ViewModel?

Heredé una base de código escrita en ASP.Net MVC 4. Cada método de publicación toma una FormCollection . Además de la molestia de tener que acceder a los valores a través de cadenas entrecomilladas, también genera inconvenientes como la ModelState.IsValid usar elementos como los ModelState.IsValid o [AllowHtml] en las propiedades de mi ViewModel. De hecho, crearon clases de ViewModel para cada una de sus vistas (aunque son simplemente envoltorios directos alrededor de las clases reales de Entity Framework Model), pero solo se usan para los métodos GET.

¿Hay algo que me pierda sobre FormCollection que da una razón por la cual esta puede ser una buena idea? Parece que solo tiene inconvenientes. Me gustaría revisarlo y “arreglarlo” usando ViewModels en su lugar. Esto tomaría un buen trabajo porque los ViewModels tienen propiedades que son interfaces y no clases concretas, lo que significa escribir un cuaderno personalizado o cambiar los ViewModels.

Pero tal vez hay algo que me falta donde tiene sentido usar FormCollection?

¿Hay alguna buena razón para usar FormCollection en lugar de ViewModel?

No. Tengo los siguientes problemas.

Problema – 1

En caso de que se FormCollection … Será obligatorio FormCollection Type Cast the Primitive Type Values ​​innecesariamente porque al obtener la entrada de un índice específico de System.Collections.Specialized.NameValueCollection , el valor que se devuelve es de tipo String . Esta situación no se producirá en el caso de View-Models fuertemente tipados.

Problema – 2

Cuando envía el formulario y va al Método de Post Acción, y View-Model como Parámetro existe en el método de Acción, tiene la provisión de devolver los Valores Publicados a su View . De lo contrario, escriba el código de nuevo para enviar de vuelta a través de TempData/ViewData/ViewBag

enter image description here

View-Models son clases normales, creadas para vincular datos a-from Views

Problema – 3

Tenemos Anotaciones de datos que se pueden implementar en View Model o Custom Validations .

enter image description here

ASP.Net MVC simplifica validaciones de modelo utilizando anotación de datos. Las anotaciones de datos son atributos que se aplican a las propiedades. Podemos crear Atributo de validación personalizado heredando la clase incorporada de Atributo de Validación.

Problema – 4

Ejemplo que tienes el siguiente HTML

  

Pregunta : ¿Cómo podemos acceder al valor de customAttr1 de arriba, por ejemplo, desde el interior del controlador?

Respuesta : Cuando se publica un formulario, solo el nombre y el valor de los elementos se publican en el servidor.

Alternativas : utilice un poco de jQuery para obtener los valores de atributo personalizados y publíquelos junto con los valores de formulario para el método de acción.

Otra opción es poner lo que tienes en tus atributos personalizados en controles ocultos

Esa es la razón, siempre preferiría usar View-Models

La única ventaja que se me ocurre es si desea usar el controlador generado automáticamente que se proporciona cuando no especifica un modelo de EF con el que se escriba fuertemente. En ese caso, sus acciones Crear y Editar utilizarán el objeto FormCollection ya que es un artefacto fiable y preexistente del marco con el que trabajará para este fin. Tal vez el desarrollador anterior eligió esta opción al crear sus controladores y se quedó con ella, ya que Visual Studio debe saber lo que está haciendo 🙂

Pero, en realidad, nunca recomendaría esta cabecera de unos pocos segundos. Siempre es mejor construir viewmodels, recomendaría mirar el esfuerzo para avanzar en esa dirección, solo por cuestiones de mantenimiento. Con el enlace de modelo y las vistas fuertemente tipadas y los helpers html, es mucho más probable que reduzca el número de errores de tiempo de ejecución como resultado de cambiar alguna cadena mágica y no darse cuenta hasta que su página explote.

Ok, veo que el consenso general aquí es que no es del agrado. Para ofrecer otra perspectiva, siempre me ha gustado utilizar formcollection pasado al controlador en acciones POST. Ofrece el uso del método TryUpdateModel del controlador que correlacionará la colección con su clase fuertemente tipada. TryUpdateModel también tiene sobrecargas que le permiten listar en blanco las propiedades del modelo que desea permitir que se actualice.

 if (TryUpdateModel(viewModel, new string[] { "Name" })) { //Do something } 

Todavía permite todo el enlace de modelo que desee, pero ayuda a mantener actualizada cualquier otra cosa que no sea la propiedad “Nombre” en mi modelo de vista.

Puede ver más sobre el método TryUpdateModel aquí:

http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryupdatemodel(v=vs.108).aspx

Siempre hay soluciones para escapar de un FormCollection lol .. puede tener campos ocultos vinculados a las variables de su modelo de vista en el formulario al contenido de su corazón.

Las colecciones de formularios surgen principalmente de la pereza de crear un modelo de vista, pero aún así se toman el tiempo de intentar descifrar cómo obtener los valores en su controlador: P

Creo que se creó simplemente al principio de MVC como una alternativa al uso de vistas fuertemente tipadas cuando se tienen formas muy simples, en los días en que todos usaban ViewBag 🙂 … y una vez que lo tenían allí no podían solo sácalo tan simple como eso.

¿Tal vez pueda usarlo si está absolutamente seguro de que su vista nunca tendrá más de una entrada de formulario? Probablemente todavía sea una mala idea, aunque ..

No puedo encontrar ningún artículo reciente sobre las ventajas de las colecciones de formularios, mientras que las vistas fuertemente tipadas están en todas partes.

Sí. A veces, puede ser útil. Aquí hay un ejemplo:

Digamos que tenemos en nuestro db ” date_and_time_field “.

En Razor View, queremos usar dos campos de formulario. La primera “Fecha” (tal vez con jQuery UI Datepicker). El segundo “Hora”.

En la Acción del controlador, compondremos el “campo date_and_time_field” por medio de Request.Form["Date"] y Request.Form["Hour"] .

Hay otros escenarios donde puede ser útil:

  • Una tabla cruzada (con checkBoxes en la vista Razor)

  • La colección Request.Unvalidated().Form (quizás esto no sea parte de su pregunta: no quiero estar fuera del tema)

El encuadernador de modelo predeterminado hará casi todo lo que necesita hacer. FormCollection a FormCollection una vez, solo para luego descubrir cómo vincular matrices de elementos en una colección en ViewModel .

Solo ve ViewModel . Mejor todo, por cada razón enumerada.

Con la form collection , podrá obtener todos los valores dentro del formulario. Puede haber situaciones en las que deba pasar algunos valores adicionales del formulario que pueden no ser parte de su view model .

Solo tome un ejemplo de pasar 10 valores ocultos del formulario. La colección de formularios tiene sentido.

La única dificultad que puede enfrentar es el tipo de casting. Todos los elementos de la colección de formularios que obtienes serán de cadena; Es posible que deba type cast según su requerimiento.

También la validación del modelo de estado es otra área donde puede enfrentar un desafío.

Siempre puede agregar las propiedades de la colección de formularios a sus firmas de métodos. Se llenarán automáticamente por valores de formulario con las claves correspondientes.

Bien con Forms Collection , encontrará una forma rápida de obtener los valores de un formulario. De lo contrario, debe crear una clase que imite los Campos de formulario y las personas son perezosas en ocasiones para crear clases personalizadas para Formularios menos importantes / poco utilizados.

No, no hay ningún beneficio adicional (de hecho limitado) de la recostackción de formularios en una clase personalizada como parámetros de acción, y debe evitarse siempre que sea posible.

Respondiendo a la pregunta del título: sí.

Hay algunas situaciones en las que se necesita FormCollection . Por ejemplo, supongamos un ViewModel que tiene una propiedad que implementa la relación 1 a N (en el caso concreto, un TimesheetViewModel con ICollection ), y el Controller debe realizar una validación entre las entradas de tiempo para no tener una colisión de tiempo entre el tiempo de finalización de una entrada y la hora de inicio de la siguiente entrada. Para marcar una entrada relacionada con un error de validación, ¿cómo puede recuperarse el índice de línea?

Bueno, con el enlace de modelo predeterminado, el valor de índice se pierde en la lógica del controlador. Afortunadamente, FormController almacena el índice que utilizó en la Vista y se puede realizar una validación más específica.