2011-06-24 70 views
12

我有单独的模型和视图模型类。其中viewmodel类只进行UI级别验证(请参阅:Validation: Model or ViewModel)。验证Model和ViewModel的最佳实践

我可以在控制器中验证模型(vewmodel)是否有效。

问: 如何验证模型(带有数据注释的主要实体)。

我没有开发使用模型对象的视图模型。只需复制属性并添加该特定视图中可能需要的所有属性即可。

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

应该做这样的事情:

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

我在想什么基类是添加(业务实体)此验证的技术,并验证它,当我从映射视图模型类到商业实体。

有什么建议吗?

回答

9

1)在从用户检索信息的模型上使用流畅的验证。它更灵活,然后数据注释,更容易测试。

2)您可能需要查看automapper,通过使用automapper,您不必编写x.name = y.name

3)对于您的数据库模型,我会坚持数据注释。下面

一切都基于新的信息

首先,所有你应该把验证两个位置,就像你现在所做的实际模型验证,这是我会怎么做。 免责声明:这不是一个完美的方式

首先,所有更新UserViewModel

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

然后更新行动方法

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

现在的用户模型,可以得到棘手和你有很多可能的解决方案。我想出了一个解决方案(可能不是最好的)如下:

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

末一些单元测试,以检查自己的代码:

[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

珠三角@Serghei其实我想知道我该怎么办验证模型类(不绑定查看)。保持我的视图具有来自不同模型类(在ViewModel类中)的属性,以满足特定视图的所有需求。 – Yahya

+0

@Yahya你能举一个例子吗?指出您应该在哪里以及如何进行验证会更容易。 – David

+0

prd我已经在原始问题中为您添加了示例代码。我希望现在有道理。 – Yahya