2011-06-24 21 views
12

Mam oddzielne klasy modelu i widoku. Tam, gdzie klasy viewmodel obsługują tylko sprawdzanie poziomu interfejsu użytkownika (zobacz: Validation: Model or ViewModel).Najlepsze praktyki sprawdzania poprawności dla modelu i ViewModel

Mogę zweryfikować działanie po akcji w kontrolerze, którego model (vewmodel) jest poprawny.

Pytanie: W jaki sposób sprawdzić poprawność modelu (główna jednostka z adnotacjami danych).

Nie rozwijam viewmodel za pomocą obiektu modelu. Wystarczy powielić właściwości i dodać wszystkie właściwości wymagane w danym widoku.

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

powinien zrobić coś takiego:

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

Co mam na myśli jest dodanie tej techniki walidacji w klasie bazowej (z jednostki gospodarczej) i zweryfikować go, kiedy jestem odwzorowanie klasa viewmodel do jednostki biznesowej.

Wszelkie sugestie?

Odpowiedz

9

1) Użyj biegłego sprawdzania poprawności w modelu, który pobiera informacje od użytkownika. jest bardziej elastyczny niż adnotacja danych i łatwiejszy do przetestowania.

2) Możesz zajrzeć do automappera, używając automappera nie musisz pisać x.name = y.name.

3) Dla modelu bazy danych trzymałbym się adnotacji danych.

Wszystko poniżej jest oparta na nowych informacjach

Pierwszy i wszystko należy umieścić walidacji zarówno położenie jak ty teraz do rzeczywistej walidacji modelu jest to w jaki sposób to zrobić. Uwaga: nie jest to idealny sposób

Przede wszystkim Aktualizacja UserViewModel do

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

Następnie zaktualizować metodę działania w celu

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

teraz na modelu użytkownika robi się trudne i masz wiele możliwych rozwiązań.Rozwiązanie wymyśliłem (prawdopodobnie nie najlepszy) jest następujący:

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

Ostatnio niektóre testy jednostkowe, by sprawdzić mój własny kod:

[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); 
     } 
    } 
+0

PRD @Serghei I rzeczywiście chciał się dowiedzieć, jak to zrobić sprawdź klasę modelu (która nie jest wiązana do wyświetlenia). Utrzymywanie, że moje widoki mają właściwości z różnych klas modeli (w klasie ViewModel), aby spełnić wszystkie wymagania w tym konkretnym widoku. – Yahya

+0

@Yahya Czy możesz podać przykład? łatwiej będzie wskazać, gdzie powinieneś i jak wykonać walidację. – David

+0

prd Dodałem przykładowy kod do pierwotnego pytania dla ciebie. Mam nadzieję, że teraz ma sens. – Yahya