2010-12-05 9 views
5

モデルといくつかの追加のプロパティがあるViewModelがあります。モデルとプロパティの検証は実行されますが、モデルの検証のみがチェックされ、プロパティの検証は無視されます。ViewModelでMVCモデルの検証が機能しない

モデル:

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

私はフォームを送信してパスワードを空にしておくと、通過します。私が空白のままにしておくと、顧客フィールドにエラーが表示されます(パスワードフィールドを除く)

答えて

9

これは正常です。あなたのPOSTコントローラアクションは、ビューモデルではなくパラメータとしてCustomerをとります。検証はモデルバインダーによって実行されるため、モデルバインダーが要求パラメーターからCustomerオブジェクトをバインドしようとすると、検証が呼び出されます。このビューモデルで検証を実行するには、POSTアクションでビューモデルをパラメータとして使用する必要があります。現在のところ、ポストアクション内のこのビューモデルで行うことは、コンストラクタを呼び出すことであり、コンストラクタを呼び出すことによってバリデーションが行われることはありません。

だからあなたのPOSTアクションがなる必要があります:あなたはそれがすでにビューモデルの一部であるように、第2のアクションの引数としてパスワードを渡す必要はありませんか

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

注意してください。

+0

それは、ロジックが鳴り、それを修正するのに役立ちます。私はこのケースでモデルバリデーションを使用する最良のソリューションを見つけるまで、コントローラ内の他のプロパティの検証を別々に行います。どうもありがとう。 – Nestor

+0

ビューをViewModelをポストコントローラに渡す方法を教えてください。私は前に試してみましたが、フォームがViewModelを受け取るので、 "nullable parameter"エラーを表示しますが、ポストバックするとViewModel内の各モデルに分割されてポストコントローラのシグネチャと一致しないため、 ViewModelパラメータ。ポストコントローラで、ViewModelの単一のパラメータではなく、個別のパラメータとして各モデルを取得するように強制します。 – Nestor

+0

@Nestor、ViewにViewModelを渡すようにするには、このビューに '

'と、渡されるViewModelのプロパティに対応するPutテキストフィールドを含めることができます。リクエストで送信されたものだけがViewModelにバインドされることに注意してください。 –

0

これはパスワードプロパティの設定者がprivate setに設定されているためです。顧客フィールドの残りのセッターはすべてパブリックセッターです。プロパティに有効な値のセッター検査がない場合は、必須ではありません。

+0

コンストラクタが呼び出されると、コンストラクタが呼び出されます。コンストラクタはこれらのプライベートプロパティの設定を担当します。これらのプロパティはクラス外からアクセスする必要はありません。理由は、モデルがViewModelではなく呼び出されているというDarinの発言のように、ViewModelのバインディングがないので、検証がトリガーされません。 – Nestor

関連する問題