【问题标题】:ASP.NET MVC Model validation not working on ViewModelASP.NET MVC 模型验证不适用于 ViewModel
【发布时间】:2010-12-05 12:33:19
【问题描述】:

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

如果我提交表单时将密码留空,它就会通过。如果我将客户字段留空,它会显示错误(密码字段除外)

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    这很正常。您的 POST 控制器操作将 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);
         }
    }
    

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

    【讨论】:

    • 这听起来很合乎逻辑,可以帮我解决它。我将在控制器内部单独进行其他属性验证,直到找到在这种情况下使用模型验证的最佳解决方案。非常感谢。
    • 如何让 View 将 ViewModel 传递给 post 控制器?我之前尝试过,它显示“可空参数”错误,因为表单接收到 ViewModel,但是当回发时,它会将其分解为 ViewModel 内的每个模型,因此它无法匹配 post 控制器上的签名,然后控制器将 null 设置为ViewModel 参数,这迫使我在后控制器中将每个模型作为单独的参数而不是 ViewModel 的单个参数。
    • @Nestor,要使视图将 ViewModel 传递给控制器​​,您可以在此视图中包含 &lt;form&gt;,并在与将要传递的 ViewModel 的属性相对应的文本字段中包含。请记住,只有请求中发送的内容才会绑定到 ViewModel。
    • 我的意思是,像我的示例这样的 ViewModel,ViewModel 包含一个 Customer 对象和一个字符串 Password,到目前为止,我无法让 View 将类似的东西传递给一个 ViewModel,换句话说,复杂的模型就像this 不能被 View 绑定,只能绑定内部的 Customer 对象模型和字符串密码。如果我编写像 Create(ViewModel model) 这样的后控制器,我会收到“可空参数”错误,只有 Create(Customer newCustomer, string password) 可以。
    【解决方案2】:

    我相信这是因为您的密码属性的设置器设置为private set。其余客户字段上的所有设置器都是公共设置器。如果属性没有设置器检查有效值,则不需要。

    【讨论】:

    • 模型绑定时调用构造函数,构造函数负责设置那些私有属性,不需要从类外部访问这些属性。原因就像 Darin 所说的,只调用了 Model,而不是 ViewModel,所以没有绑定 ViewModel,所以没有触发验证。
    猜你喜欢
    • 2013-11-23
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 2015-02-26
    • 1970-01-01
    • 2011-03-04
    • 2010-11-11
    相关资源
    最近更新 更多