Pergunta

usando ASP.NET MVC, tenho um modelo ao qual estou anexando atributos para poder usar a validação vinculada ao modelo MVC, mas para isso não quebra a regra do MVC, onde você está colocando itens que pertencem à View, no Model?Espero não tentar ser inteligente, mas estou curioso para saber a opinião dos outros.

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; }
}
Foi útil?

Solução

Sim.É por isso que você deve usar ViewModels.

Outras dicas

Você pode, mas não é obrigatório, colocar esses atributos de validação em seu modelo.

Mas é melhor usar um ViewModel:

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

E na sua visão, em vez de:

@model YourProject.Models.Payments

você usa:

@model YourProject.Models.PaymentsViewModel

para validação.

Isso viola o MVC no sentido estrito, sim, provavelmente.Há momentos em que não há mal nenhum em violar isso?Claro.No entanto, existem mecanismos para ajudá-lo e manter as preocupações separadas.

Você pode usar seus objetos de domínio persistentes nas visualizações e validá-los, mas quando sua visualização começa a ficar complicada, os ViewModels se tornam uma necessidade.Para modelos de domínio simples ou visualizações somente visualização (não edições/criações), às vezes eu falsifico um pouco e os envio para a visualização como parte de um objeto composto:

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

No entanto, para criar e editar cenários, os ViewModels são muito melhores.Eles permitem controle total sobre os dados que estão sendo enviados para a visualização e de a vista.

Se você estiver usando EF 4.1 e CodeFirst, sim, você acabará com alguma duplicação de atributos e propriedades entre o domínio e o ViewModel.Isso é inevitável, mas oferece a flexibilidade de fazer diferentes validações específicas para a visualização.

Achei útil ter uma camada extra de proteção no controlador ao salvar o objeto de domínio, caso eu tenha perdido alguma validação na visualização:

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

A próxima pergunta a ser feita é como você mapeia entre o modelo de domínio e o ViewModel.Existem várias estratégias e ferramentas por aí - AutoMapper e Injetor de valor (sim, escrito errado).Pessoalmente, tenho usado o ValueInjecter, embora se você configurar uma camada de mapeamento, poderá tentar ambos.Descobri que nenhum deles funcionará em 100% dos casos, ou pelo menos consegui descobrir como fazer o que precisava, mas um serviço de mapeamento facilita a definição de mapas personalizados da esquerda para a direita.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top