webdevqa.jp.net

コントローラーメソッド内で変更されたViewModelを再検証しますか?

[〜#〜] edit [〜#〜]-MVC4 Dev Previewを使用しています...

FishingTripクラスの編集ページを実装しています。 FishingTripには、単純なCrewオブジェクトの子コレクションが含まれます(例:FishingTripID、CrewID、CrewPosition)。

Jarrett Meyerのアプローチ を使用して、Crewコレクションの追加、編集、削除を行っています。控えめな検証を使用して、CrewのプロパティがすべてRequiredであることを指定しています。

私の問題:(Jarrettの方法に従って)リストから項目を論理的に削除するとき、その項目を検証したくありません。

論理的に削除されたアイテムの控えめな検証を無効にするために、クライアント側の「removeRow」メソッドを微調整し、空のフィールドを含むアイテムがあるにもかかわらずフォームが投稿されるようにしました。

私のコントローラーメソッド[HttpPost] EditModelState.IsValidはfalseから始まります(予想どおり-空白のフィールドを含む論理的に削除されたアイテムのため)。したがって、ViewModelからそのアイテムを削除します。..ModelState.IsValidはまだfalseです。

要約すると、コントローラーメソッド内でViewModelを変更して問題のあるアイテムを削除し、ある種の「再検証」を呼び出して、ModelState.IsValid trueと表示されます。

何か案は?

53
Merenzo

問題のあるアイテムを削除したら、次のようにModelStateをクリアして再度検証します。

ModelState.Clear();
TryValidateModel(crew);  // assumes the model being passed is named "crew"

TryValidateModelメソッドを使用するときは注意してください。このメソッドは、モデルのネストされたオブジェクトを検証しないためです(@Merenzoが述べたように)。

125
counsellorben

ゲームに遅れましたが、それでも:モデルを検証する方法を探していましたafterモデル(より正確には-ネストされたコレクションのアイテム)-およびTryValidateModelはネストされたオブジェクトを処理しないため、私にとってはうまくいきませんでした。

最後に、カスタムモデルバインダーで解決しました。

public class MyItemModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(MyItemModel))
        {
            MyItemModel item = (MyItemModel)bindingContext.Model;
            //do required tweaks on model here 
            //(I needed to load some additional data from DB)
        }
        //validation code will be called here, in OnModelUpdated implementation
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

モデルクラス:

[ModelBinder(typeof(MyItemModelBinder))]
public class MyItemModel : IValidatableObject
{
    //...
}
2
lxa