2010-12-05 75 views
5

我有ViewModel裏面有一個模型和一些額外的屬性。對模型和屬性進行了驗證,但是在執行時只檢查模型上的驗證,忽略屬性中的驗證。ASP.NET MVC模型驗證不能在ViewModel上工作

的型號:

[MetadataType(typeof(Customer_Validation))] 
public partial class Customer 
{ 
} 

public class Customer_Validation 
{ 
    [Required(ErrorMessage="Please enter your First Name")] 
    public string FirstName { get; set; } 

    [Required(ErrorMessage = "Please enter your Last name")] 
    public string LastName { get; set; } 

    [Required(ErrorMessage = "Sorry, e-mail cannot be empty")] 
    [Email(ErrorMessage="Invalid e-mail")] 
    public string Email { get; set; } 
} 

視圖模型

public class RegisterViewModel 
{ 
    public Customer NewCustomer { get; private set; } 

    [Required(ErrorMessage="Required")] 
    public string Password { get; private set; } 

    public RegisterViewModel(Customer customer, string password) 
    { 
     NewCustomer = customer; 
     Password = password; 
    } 
} 

的控制器

public ActionResult Create() 
{ 
    Customer customer = new Customer();  
    RegisterViewModel model = new RegisterViewModel(customer, "");  
    return View(model); 
} 

[HttpPost] 
public ActionResult Create(Customer newCustomer, string password) 
{ 
    if (ModelState.IsValid) 
    { 
     try 
     { 
      // code to save to database, redirect to other page 
     } 
     catch 
     { 
      RegisterViewModel model = new RegisterViewModel(newCustomer, password); 
      return View(model); 
     } 
    } 
    else 
    { 
     RegisterViewModel model = new RegisterViewModel(newCustomer, password); 
     return View(model); 
    } 
} 

@using (Html.BeginForm()) 
{ 
    <table> 
    <tr> 
    <td>First Name:</td> 
    <td>@Html.TextBoxFor(m => m.NewCustomer.FirstName)</td> 
    <td>@Html.ValidationMessageFor(m => m.NewCustomer.FirstName)</td> 
    </tr> 
    <tr> 
    <td>Last Name:</td> 
    <td>@Html.TextBoxFor(m => m.NewCustomer.LastName)</td> 
    <td>@Html.ValidationMessageFor(m => m.NewCustomer.LastName)</td> 
    </tr> 
    <tr> 
    <td>E-mail:</td> 
    <td>@Html.TextBoxFor(m => m.NewCustomer.Email)</td> 
    <td>@Html.ValidationMessageFor(m => m.NewCustomer.Email)</td> 
    </tr> 
    <tr> 
    <td>Password:</td> 
    <td>@Html.TextBoxFor(m => m.Password)</td> 
    <td>@Html.ValidationMessageFor(m => m.Password)</td> 
    </tr> 
    </table> 

    <input type="submit" value="Register" /> 
} 

如果我提交的表格留下密碼空白它讓我們通過。如果我留下空的客戶字段它確實顯示錯誤(密碼字段除外)

回答

9

這很正常。您的POST控制器操作需要Customer作爲參數,而不是視圖模型。驗證由模型聯編程序執行,所以當模型聯編程序試圖從請求參數綁定Customer對象時,它將調用驗證。如果您希望在此視圖模型上執行驗證,則您的POST操作需要將視圖模型作爲參數。目前,你在post操作中使用這個視圖模型所做的一切就是調用構造函數,調用構造函數根本不會觸發任何驗證。

所以,你的POST操作應該成爲:

[HttpPost] 
public ActionResult Create(RegisterViewModel newCustomer) 
{ 
    if (ModelState.IsValid) 
    { 
     // code to save to database, redirect to other page 
    } 
    else 
    { 
     return View(newCustomer); 
    } 
} 

注意到你怎麼不需要通過密碼作爲第二個操作參數,因爲它已經是您的視圖模型的一部分。

+0

這聽起來很合邏輯,可以幫我修復它。我將單獨在控制器內部進行其他屬性驗證,直到找到使用模型驗證的最佳解決方案。非常感謝。 – Nestor 2010-12-06 04:09:01

0

我相信這是因爲您的密碼屬性上的setter設置爲private set。所有其他客戶領域的設置人員都是公共設置人員。當屬性沒有設置檢查有效值不是必需的。

+0

當模型綁定到構造函數時,構造函數負責設置這些私有屬性,不需要從類外部訪問這些屬性。理由就像Darin說的那樣,只有Model被調用,而不是ViewModel,因此ViewModel沒有綁定,所以沒有驗證觸發。 – Nestor 2010-12-06 04:16:15