ASP.NET MVC模型验证不适用于ViewModel

时间:2010-12-05 12:33:19

标签: c# asp.net-mvc

我有ViewModel,它包含一个Model和一些额外的属性。模型和属性上有验证,但执行时,只检查模型验证,忽略属性验证。

模特:

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

ViewModel

 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" />
 }

如果我提交表单,请将密码保留为空,请将其删除。如果我将客户字段留空,则会显示错误(密码字段除外)

2 个答案:

答案 0 :(得分:10)

这是正常的。您的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);
     }
}

请注意,您不需要将密码作为第二个操作参数传递,因为它已经是视图模型的一部分。

答案 1 :(得分:0)

我认为这是因为您的密码属性的设置者设置为private set。其余客户字段中的所有设置者都是公共设置者。当属性没有setter检查有效值时,不需要。