Convalida di best practice per il Modello e ViewModel

Ho separato modello e classi viewmodel. Dove viewmodel classi di farlo solo a livello UI di convalida (riferimento: Convalida del Modello o ViewModel).

Posso verificare sul post di azione in un controller di quel modello (vewmodel) è valido.

Ask:
Come faccio a validare il modello (l’entità principale con le annotazioni di dati).

Io non sono in via di sviluppo il viewmodel utilizzando il modello a oggetti. Appena duplicare la proprietà e l’aggiunta di tutte le proprietà di capacità eventualmente richiesti in quella particolare prospettiva.

//Model Class
public class User
{
    [Required]
    public string Email {get; set;}

    [Required]
    public DateTime Created {get; set;}
}

//ViewModel Class
public class UserViewModel
{
    [Required]
    public string Email {get; set;}

    [Required]
    public string LivesIn {get; set;}
}

//Post action
public ActionResult(UserViewModel uvm)
{
    if( ModelState.IsValid)
        //means user entered data correctly and is validated

    User u = new User() {Email = uvm.Email, Created = DateTime.Now};
    //How do I validate "u"?

    return View();
}

Dovrebbe fare qualcosa di simile a questo:

var results = new List<ValidationResult>();
var context = new ValidationContext(u, null, null);
var r = Validator.TryValidateObject(u, context, results);

Quello che sto pensando è l’aggiunta di questa tecnica di validazione della classe base (di entità di business), e verificare, io mi mappatura dal viewmodel classe di entità di business.

Qualche suggerimento?

InformationsquelleAutor Yahya | 2011-06-24



2 Replies
  1. 10

    1) Utilizzare fluentemente la validazione del modello che recupera informazioni da parte dell’utente. è più flessibile e quindi i dati di annotazione e più facili da verificare.

    2) che Si potrebbe desiderare di guardare in automapper, utilizzando automapper non devi scrivere x.name = y.name.

    3) Per il vostro modello di database avrei aderire ai dati-annotazioni.

    Tutto ciò che segue è basato sulla nuova informazione

    Prima e tutti si dovrebbe mettere la convalida sia come location che hai fatto ora per l’attuale modello di validazione questo è come lo faccio. Disclaimer: questo non è il modo perfetto

    Primo aggiornamento il UserViewModel per

    public class UserViewModel
        {
            [Required()]
            [RegularExpression(@"^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9][email protected]((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$")]
            public String Email { get; set; }
        }

    Quindi aggiornare il metodo di azione per

            //Post action
            [HttpPost]
            public ActionResult register (UserViewModel uvm)
            {
                //This validates the UserViewModel
                if (ModelState.IsValid)
                {
    
                    try
                    {
                        //You should delegate this task to a service but to keep it simple we do it here
                        User u = new User() { Email = uvm.Email, Created = DateTime.Now };
                        RedirectToAction("Index"); //On success you go to other page right?
                    }
                    catch (Exception x)
                    {
                        ModelState.AddModelError("RegistrationError", x); //Replace x with your error message
                    }
    
                }       
    
                //Return your UserViewModel to the view if something happened               
                return View(uvm);
            }

    Ora per il modello di utente diventa difficile e si dispone di molte soluzioni possibili. La soluzione mi è venuta (probabilmente non il migliore) è il seguente:

    public class User
        {
            private string email;
            private DateTime created;
    
            public string Email
            {
                get
                {
                    return email;
                }
                set
                {
                    email = ValidateEmail(value);
                }
            }
    
            private string ValidateEmail(string value)
            {
                if (!validEmail(value))
                    throw new NotSupportedException("Not a valid email address");     
    
                return value;
            }
    
            private bool validEmail(string value)
            {
                return Regex.IsMatch(value, @"^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9][email protected]((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$");
            }

    Ultimo alcune unità di test per controllare il mio codice:

       [TestClass()]
        public class UserTest
        {
    
            ///<summary>
            ///If the email is valid it is stored in the private container
            ///</summary>
            [TestMethod()]
            public void UserEmailGetsValidated()
            {
                User x = new User();
                x.Email = "[email protected]";
                Assert.AreEqual("[email protected]", x.Email);
            }
    
            ///<summary>
            ///If the email is invalid it is not stored and an error is thrown in this application
            ///</summary>
            [TestMethod()]
            [ExpectedException(typeof(NotSupportedException))]
            public void UserEmailPropertyThrowsErrorWhenInvalidEmail()    
           {
               User x = new User();
               x.Email = "blah blah blah";
               Assert.AreNotEqual("blah blah blah", x.Email);
           }
    
    
            ///<summary>
            ///Clears an assumption that on object creation the email is validated when its set
            ///</summary>
            [TestMethod()]
            public void UserGetsValidatedOnConstructionOfObject()
            {
                User x = new User() { Email = "[email protected]" };
                x.Email = "[email protected]";
                Assert.AreEqual("[email protected]", x.Email);
            }
        }
    • prd @Serghei in realtà io volevo sapere come posso fare per convalidare il modello di classe (che non è associato a vista). Mantenere il mio punto di Vista hanno proprietà diverse classi del modello (in una classe ViewModel) per soddisfare tutti i requisiti in quella particolare prospettiva.
    • Puoi postare un esempio? sarà più facile per il punto dove si dovrebbe, e come, per eseguire la convalida.
    • prd ho aggiunto un codice di esempio per la domanda originale per voi. Spero che senso ora.
    • ho aggiornato il mio post con una possibile soluzione, tuttavia la sua non è dei migliori
    • prd Grazie per la soluzione. Purtroppo questo aspetto non è molto ordinata. Per adesso, come entità di business non sono mission critical, io sono solo il vita con nessun controllo su di loro. Il tutto facendo la convalida viewmodel. Per la mappatura, ho preso il tuo consiglio e sto usando Automapper.

Lascia un commento