2011-05-18 33 views
6

usando ASP.NET MVC, tengo un modelo, al que estoy adjuntando atributos para que pueda usar la validación de MVC Model bound, pero a no se rompe la regla de MVC, donde está poniendo artículos que pertenecen a la Vista, al Modelo? Espero que no intente ser inteligente, sin embargo, siento curiosidad por las opiniones de los demás.La validación del modelo ASP.NET MVC rompe la regla MVC?

public class Payments 
{ 
    [DataType(DataType.Text)] 
    [DisplayFormat(NullDisplayText="")] 
    [Display(Name="Payment Id")] 
    [Required(ErrorMessage="Required")] 
    public int PaymentId { get; set; } //todo: make this into a dropdown 

    [DataType(DataType.Text)] 
    [Display(Name="Bill Name")] 
    [Required(ErrorMessage = "Required")] 
    public string PaymentName { get; set; } 

    [DataType(DataType.Date)] 
    [Display(Name="Date to Post Payment")] 
    [Required(ErrorMessage = "Required")] 
    public DateTime PaymentDate { get; set; } 

    [DataType(DataType.Currency)] 
    [Range(0, 922337203685477.5807)] 
    [Required(ErrorMessage = "Required")] 
    public double PaymentAmount { get; set; } 
} 

Respuesta

10

Sí. Es por eso que deberías usar ViewModels.

+0

No entiendo la palabra "ViewModel" en el contexto de MVC. Entiendo que "MVC" es arena para Model-View-Controller.Y entiendo "MVVM" para representar Model-View-ViewModel. Entonces, si estamos hablando de MVC, ¿por qué se habla de ViewModels? –

+0

Sí, esta respuesta es incorrecta y también viola MVC ... Modelo! = Entidad –

+0

Es importante que el sastre responda y debata sobre el contexto de la pila de tecnología a mano. Modelos y modelos de vista significan algo cuando se trata de ASP.NET MVC, pero no cuando se lee Martin Fowler. El concepto original de MVC no se parece en nada a las implementaciones reales utilizadas en la web en casi todos los idiomas. – jfar

10

Puede, pero no tiene que, poner esos atributos de validación en su modelo.

Pero es mejor utilizar un modelo de vista:

public class PaymentsViewModel 
{ 
    [DataType(DataType.Text)] 
    [DisplayFormat(NullDisplayText="")] 
    [Display(Name="Payment Id")] 
    [Required(ErrorMessage="Required")] 
    public int PaymentId { get; set; } //todo: make this into a dropdown 

    [DataType(DataType.Text)] 
    [Display(Name="Bill Name")] 
    [Required(ErrorMessage = "Required")] 
    public string PaymentName { get; set; } 

    [DataType(DataType.Date)] 
    [Display(Name="Date to Post Payment")] 
    [Required(ErrorMessage = "Required")] 
    public DateTime PaymentDate { get; set; } 

    [DataType(DataType.Currency)] 
    [Range(0, 922337203685477.5807)] 
    [Required(ErrorMessage = "Required")] 
    public double PaymentAmount { get; set; } 
} 

Y en su opinión, en lugar de:

@model YourProject.Models.Payments 

que utilice:

@model YourProject.Models.PaymentsViewModel 

para su validación.

+0

¿Dónde está el mejor lugar para poner la clase ViewModel? Digamos que tiene dos soluciones: MyProject.UI y MyProject.Models, y la clase Payment es MyProjects.Models.Payment. ¿Es mejor poner ViewModel en MyProject.UI.Models.PaymentViewModel o MyProject.Models.PaymentViewModel? –

+1

@WeekendWarrior: Realmente no importa dónde ponerlo en realidad. Tengo un habito de hacer 2 carpetas: Modelos y Modelos de Vista y ponerlos allí. – Matthias

+0

¿Cómo se vería su modelo? Parece más bien argumentos semánticos aquí, aunque es cierto que es un simple ejemplo. – nicodemus13

1

Viola MVC en el sentido estricto, sí, probablemente. ¿Hay momentos en que no hay daño al violar eso? Por supuesto. Sin embargo, existen mecanismos para ayudarlo y mantener las preocupaciones por separado.

Puede usar los objetos de su dominio persistente en las vistas y validarlos, pero cuando su vista se vuelve complicada, ViewModels se convierte en una necesidad. Para los modelos simples de dominio muertas o vistas de sólo visualización (no edita/crea), a veces me voy a Fudge un poco y enviarlos a la vista como parte de un objeto compuesto:

class MyViewModel 
{ 
    public MyDomainModel DomainObj; 
    public int OtherViewInfo; 
} 

Sin embargo, para crear y editar escenarios, ViewModels son mucho mejores. Le permiten un control total sobre los datos que se envían a la vista y desde la vista.

Si está utilizando EF 4.1 y CodeFirst, entonces sí, terminará con una cierta duplicación de atributos y propiedades entre el dominio y el ViewModel. Esto es inevitable, pero le brinda la flexibilidad de realizar validaciones diferentes específicas de la vista.

que he encontrado que es útil tener una capa adicional de protección en el controlador cuando en realidad salvar el objeto de dominio en caso de que echaba de menos alguna validación en la vista:

public class MyController : Controller 
{ 
    [HttpPost] 
    public ActionResult Edit(int id, MyViewModel model) 
    { 
     try 
     { 
      ...Do stuff, check ModelState.IsValid... 
      _context.SaveChanges() 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      // Catch any validation errors on the domain that weren't duplicated 
      // in the viewmodel 
      ModelState.AddModelError("Form", dbEx); 
     } 

     return View(model); 
    } 
} 

La siguiente pregunta es cómo mapea entre el modelo de dominio y ViewModel. Hay una serie de estrategias y herramientas por ahí: AutoMapper y ValueInjecter (sí, deletreado incorrectamente). Personalmente, he estado usando ValueInjecter, aunque si configura una capa de mapeo, puede probar ambas. He descubierto que ninguno de los dos funcionará en el 100% de los casos, o al menos podría descubrir cómo hacer lo que necesitaba, pero un servicio de mapas facilita la definición de mapas personalizados de izquierda a derecha.

Cuestiones relacionadas