2012-02-13 16 views
1

私はASP.Net MVC3に基づいてWebアプリケーションを持っています。私は、ユーザーがドロップダウンから作成するサブタイプを選択するまでモデルタイプを知らない「作成」ビューが必要です。この問題を解決するために、私はそれぞれの派生モデルタイプに対してShared/EditorTemplatesの下にエディタテンプレートを作成しました。これにより、ビューモデルに強く型付けされた単一の "Create.cs"を作成することができます。ビューモデルには、列挙型と複合型の2つのメンバしかありません。考えられるのは、ビューは最初にドロップダウン(列挙型メンバーのエディタ)のみを表示し、ユーザが最初に指定された「モデルタイプ」(ドロップダウン選択値)を送信すると、POSTアクションは「モデルタイプ可能なすべての「モデルタイプ」の基本タイプであるビューモデルの単一の複合メンバの正しい派生モデルタイプを指定してインスタンス化します。プロパティが設定されていてもTryUpdateModelがfalseを返すのはなぜですか?

抽象+派生型モデルオブジェクト...

public abstract class MyModelBase 
{ 
    public MyModelType_e ModelType {get; set; } 
    [Required] 
    public string Name { get; set; } 
} 

public class DerivedType1 : MyModelBase 
{ ... } 

public class DerivedType2 : MyModelBase 
{ ... } 

public class DerivedType3 : MyModelBase 
{ ... } 

次のように私は、複雑なビューモデルを持っている...

public enum MyModelType_e 
{ 
    DerivedType1 = 0, 
    DerivedType2 = 1, 
    DerivedType3 = 2 
} 

public class MyModelCreate 
{ 
    public MyModelType_e ModelTypeForSelectList { get; set; } 
    public MyModelBase ModelBase { get; set; } 
} 

マイGETコントローラのアクションがため上記のビューモデルをインスタンス化しますMyModelType_e enum +モデルの "ModelBase"プロパティの値が最初はnullであることに基づいて表示されるドロップダウンリストのみです。だから、GETアクションメソッドは次のようになります...

[HttpGet] 
public ActionResult Create() 
{ 
    return View(new MyModelCreate()); 
} 

注キャップ内のコメントは得られた(それはModelBaseのプロパティを設定していても(下記参照)TryUpdateModelが失敗したということである私の問題の核心について怒鳴ります問題は由来が、ここで理解するための私の見解です期待通りに対応するフォームの値に型)メンバー...

[HttpPost] 
public ActionResult Create(MyModelCreate model) 
{ 
    if (model.ModelBase == null || 
     (int)model.ModelTypeForSelectList != model.ModelBase.ModelType) 
    { 
     switch (model.ModelType) 
     { 
      case MyModelType_e.DerivedType1: 
       model.ModelBase = new DerivedType1(); 
       break; 
      case MyModelType_e.DerivedType2: 
       model.ModelBase = new DerivedType2(); 
       break; 
      case MyModelType_e.DerivedType3: 
       model.ModelBase = new DerivedType3(); 
       break; 
     } 
     return View(model); 
    } 

    if (!TryUpdateModel(model.ModelBase)) 
     return View(model); // <<< THIS HAPPENS EVEN THOUGH ModelBase APPEARS TO BE UPDATED PROPERLY... 
    // For instance, I can see right here with intellisense that model.ModelBase.Name 
    // is NOT null or empty but rather is truly updated with the correct form value(s)... 

    // TODO: Insert the record, etc... (currently we never get here...) 
} 

は、したがって、上記のセクションでは...ある

@model MyNamespace.MyModelCreate 

<h2>Create</h2> 

... 

@using (Html.BeginForm()) 
{ 
    @Html.ValidationSummary(false) 
    <fieldset> 
    <legend>Input</legend> 
    <div class="editor-label"> 
    @Html.Label("Select Model Type") 
    </div> 
    <div> 
    @Html.EnumDropDownListFor(model => model.ModelType) 
    @Html.ValidationMessageFor(model => model.ModelType) 
    </div> 

    @* 
    Conditionally show the correct editor template... 
    There is one existing under ../Shared/EditorTemplates for each 
    derived type (DerivedType1, DerivedType2, DerivedType3, etc...) 
    This much is working in the sense that the correct editor fields 
    are displayed based on what the user selects in the above drop-down. 
    *@ 
    @if (Model.InputModel != null) 
    { 
     @Html.EditorFor(model => model.ModelBase); 
    } 

    <p> 
     <input type="submit" value="Continue" /> 
    </p>    
    </fieldset> 
} 

初期のPOST(モデルタイプが選択されている)では、私のPOSTアクションメソッドは設計上TryUpdateModelラインに落ちますが、何らかの理由で検証が失敗します。私が実際に理解していない部分は、ビューモデルのModelBaseメンバ上で、TryUpdateModelがNameプロパティを適切に設定していることをはっきりと見ることができますが、検証要約レポートが "Name is required"です。

私はASP.NET MVCにかなり新しいです。私はおそらく他の方法で私のリクエスト/アクションを設計することができると理解しているので、ビューは、この「マルチステップ」の問題を達成するために、私は実際にちょうど私が私が派生モデルタイプを処理するためのEditorTemplateアプローチを好きな理由できるだけ簡単なもの、などのためのつもり事前に

おかげで...

+0

あなたの 'MyModelCreate'クラスでは、あなたが示していないいくつかの' MyModelBase'タイプを使用しているようです。その定義を表示してください。 –

+0

ダーリン、それをキャッチしてくれてありがとう...私はいくつかのものを間違って(私の最後の編集で修正した)名前を変更しました。私は実際にこの問題を最近解決しましたが、まだ自分自身の答えを投稿する時間が見つかりませんでした:( – blins

答えて

0

私の解決策は基本的に2つの追加のコントローラアクション(GETとPOST)の成長でした。私は強く型付けされた../Shared/EditorTemplatesの下で別々のビューを作成しました(それぞれの派生モデルタイプに対して1つ)。このようにして、最初の「作成」POSTアクションは選択されたタイプ(モデルは希望のタイプを指定する列挙値のみ)を受け取り、次に要求された具体的なタイプの新しいインスタンスを取得する「CreateByType」のような別のコントローラアクションにリダイレクトし、正しい編集ビュー。追加の "CreateByType"コントローラアクション(GETとPOST)は、サービスレイヤからインスタンスを要求する(enum値を渡す)ため、抽象ベースを処理するだけです。それから、それぞれの具体的なタイプのEditorTemplatesの下にビューを作成しなければなりませんでした。

1

チェックModelStateTryUpdateModelの実行後にエラーが設定されるはずです。 一部のプロパティからRequired属性を削除する必要がありました。

関連する問題