2011-12-22 5 views
8

仮面ライダーの言葉では、UpdateModel()は何をするのですか。TryUpdateModel()は何ですか?私はそれが実際に何をしているのか(明確な言葉で)、それを使用するのに問題がある人だけを明確に説明することはできません。UpdateModel()は何をしますか?

VisualStudioのインテリセンスは私を助けてくれません。

[HttpPost] 
public ActionResult Index(UserViewModel vm, FormCollection form) 
{  
    var statesCheckBoxes = form["StatesList"];  

    vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

    return View(vm); 
} 

は、私はすでにvm.BA.StatesTraveledToを設定することで、私のモデルを更新されていません。のは言わせ、ので、私は私のコントローラでこれを持っている場合、私が尋ねる理由は、ありますか?なぜ私はUpdateModelを実行する必要がありますか?また、ときに私が実際にやってみてください次:

[HttpPost] 
public ActionResult Index(UserViewModel vm, FormCollection form) 
{  
    var statesCheckBoxes = form["StatesList"];  

    vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

    UpdateModel(vm); // IS THIS REDUNDANT TO THE PREVIOUS LINE? 

    return View(vm); 
} 

何も私は(私はのUpdateModel()を実行した後に)、私は何でもあることを示す何も表示されませんにModelStateの値を調べるときに起こるようですありません変更されました。 ModelState辞書に新しいキーが表示されません。

本当に混乱しています。ありがとう! ViewModelとモデルクラスのソースコードを投稿

編集ここ

public class UserViewModel 
{ 
    public BankAccount BA { get; set; } 
} 

public class BankAccount 
{ 
    public Person User { get; set; } 
    public List<string> StatesTraveledTo { get; set; } 
} 

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int Age { get; set; } 
} 
+1

ここにソースコードがあります:http://aspnet.codeplex.com/SourceControl/changeset/view/72551#266451これはかなり簡単ですが、ModelBindingContextを作成してバインドします –

+1

また、多少ですあなたがアクションの入力として受け取ったものと同じオブジェクトをビューに渡すことはまれですが、それは起こりますが、まれですが、これはそのような用途の1つではありません。通常、投稿されたデータを表すオブジェクトを入力として受け取り、ビューの別のモデルを作成します。 –

+0

ありがとうございます。モデルをビューに戻す理由は、検証目的のためです。したがって、検証に失敗した場合は、モデルとその値をビューに渡して、フォームフィールドが再生成され、エラーメッセージが表示されるようにします。申し訳ありませんが、私が示したコードでは、実際の例のようには見えません。 – SaltProgrammer

答えて

5

。これは、mvcがmodelbinderに異なるソース(フォームコレクション、ルート値、クエリ文字列など)から値を抽出し、モデルの値を入力するように指示するためです。しかし、これが起こるためには、フォームキーがモデル内のプロパティの名前と一致する必要があります。そうであれば、モデルは正しく読み込まれます。実際には、UpdateModelは何をしていますか?単純な答えはモデルバインディングだけです。違いは、それを明示的に呼び出すことだけです。上記ActionResultは、明示的なモデルが同様に結合することによって処理されることはありませんバインディング自動モデルによって処理されなかったものを、今

Public ActionResult Index() 
{ 
    UserViewModel vm = new UserViewModel(); 
    UpdateModel(vm);// it will do same thing that was previously handled automatically by mvc 
} 

のUpdateModel

を使用してのように書き換えることができるので、あなたのhtmlとの問題バインダーモデルとの問題ではありません。 MVCは正しくあなたが

vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

ような何かを書くために、あなたがそのようなことの確認を行うにはしたくない場合はなくても、あなたのモデルにそれを注入することができるので、あなたのようなネストされたビューモデルと、フォームフィールド名は慎重に細工されなければなりませんこのgoogle search

2

は、それ用のソースコードである:それはかなり簡単ですhttp://aspnet.codeplex.com/SourceControl/changeset/view/72551#266451

protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class { 
     if (model == null) { 
      throw new ArgumentNullException("model"); 
     } 
     if (valueProvider == null) { 
      throw new ArgumentNullException("valueProvider"); 
     } 

     Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties); 
    IModelBinder binder = Binders.GetBinder(typeof(TModel)); 

    ModelBindingContext bindingContext = new ModelBindingContext() { 
     Model = model, 
     ModelName = prefix, 
     ModelState = ModelState, 
     ModelType = typeof(TModel), 
     PropertyFilter = propertyFilter, 
     ValueProvider = valueProvider 
    }; 
    binder.BindModel(ControllerContext, bindingContext); 
    return ModelState.IsValid; 
} 

Thi ModelBindingContextを作成してバインドするだけです。あなたの行動が呼び出される前に、デフォルトで既にそれが起こっていると私は信じています。手動で呼び出す必要はほとんどありません。

ここではちょっと推測していますが、あなたは変則的なやり方をしているので、奇妙な結果を得ている可能性があります。あなたの行動の署名:

public ActionResult Index(UserViewModel vm, FormCollection form) 

は、UserViewModelとFormCollectionをとります。通常、人々はどちらか一方を行います(実際はFormCollectionは今日はかなりまれです)。もう一度、ここではメモリから外していますが、UpdateModelはこれらの値が既にバインドされているため、何もしないと思います。それが空の場合は、FormCollectionがsubmittd値をすべて受信(バインド)し、viewmodelがバインドするために残っていないためです。

+0

ありがとう。 Pardon私のnoobness- UpdateModel()は、アクションの前にデフォルトで実行されると言っているので、アクションから明示的に実行する必要はありません。 – SaltProgrammer

+0

私がFormCollectionを使用する理由は、ViewModelで使用されるデフォルトのモデルバインダーが、UserViewModelオブジェクト内のBankAccountオブジェクトにあるListプロパティに対して、ビュー上にあるチェックボックスのセットをバインドできないためです。私が質問に追加したソースコードを調べてください。その深いネストされたプロパティを正しくマップするために、FormCollectionから直接取得します。私が知っているFormCollectionオブジェクトを使用しない別の方法は、カスタムモデルのバインダーを作成することですが、それをもっと複雑にしたくないのですか、何か不足していますか? – SaltProgrammer

+1

ええ、ちょうどあなたがチェックボックスのための適切なタイプで必要な他の値のためのクラスを作成してください。それをFormCollectionにバインドすることができれば、それを静的型にバインドできるはずです。また、Requestオブジェクトから何かを取得することもできます。 –

0

基本的に更新モデルは、既存のモデルの新しい値を更新するために使用されます。明示的に値を割り当てる必要はありません。あなたは

public ActionResult Index(UserViewModel vm) 
{ } 

を書いて、あなたがActionResultで検査したときにvmは、あなたがビューからポストの値が含まれていることを見つけたときに何が起こるか

+0

あなたはこれを行う必要はないと言っています... vm.BA.StatesTraveledTo = statesCheckBoxes.Split( '、')。ToList (); ??? もし私がそれを行う必要がないなら、私はUpdateModel()メソッドだけを使いたいと思った場合よりも構文は何ですか? – SaltProgrammer

関連する問題