2012-02-09 14 views
5

私のビューモデルでは、私はデータベースから取り出してビューに送信するアイテムのリストを持っています。私はPostアクションを打ち、モデルを返す必要があるとき(オプションのプロパティを補充しなくても済むようにすることが可能かどうかを知りたいと思います。投稿アクションのモデルデータを再利用

ウェブフォームでは、これは必要ではありません。

:わかりませんでした。私の問題は、DropDownListsに使用するSelectListオプションです。すべてがポストされますが、ビューに戻らなければならない場合(モデルが無効です)、データベースからオプションをリロードする必要があります。これを避けることができるかどうかを知りたい。

私のviewmodel:

public class TestModel 
{ 
    public TestModel() 
    { 
     Departments = new List<SelectListItem>(); 
    } 

    public string Name { get; set; } 
    public int Department { get; set; } 
    public IEnumerable<SelectListItem> Departments { get; set; } 
} 

マイビュー:

@model MvcApplication1.Models.TestModel  
@using (Html.BeginForm()) 
{ 
    @Html.TextBoxFor(m => m.Name) 

    @Html.DropDownListFor(m => m.Department, Model.Departments) 

    <input type=submit value=Submit /> 
} 

マイコントローラ(HttpPostにコメントを気づくん):事前に

public ActionResult Index() 
{ 
    TestModel model = new TestModel 
    { 
     Name = "Rafael", 
     Department = 1, 
     Departments = new List<SelectListItem> 
     { 
      new SelectListItem { Text = "Sales", Value = "1" }, 
      new SelectListItem { Text = "Marketing", Value = "2", Selected = true }, 
      new SelectListItem { Text = "Development", Value = "3" } 
     } 
    }; 

    // Departments gets filled from a database. 

    return View(model); 
} 

[HttpPost] 
public ActionResult Index(TestModel model) 
{ 
if (!ModelState.IsValid) 
{ 
    //Do I have to fill model.Departments again!?!?!? 

    return View(model); 
} 
else { ... } 
} 

感謝。

編集: FYI、私の解決策は、Session変数を使用することでした。

答えて

1

あなたのビューを強く入力し、コントローラメソッドを変更して、そのクラスタイプのパラメータを持つようにするだけです。

、ビュー

@model MyNamesspace.Models.MyModel 
... 
@using (Html.BeginForm()) 
{ 
    .... 
} 

であり、あなたがに投稿されたメソッドをコントローラ。

編集:コントローラに投稿する必要があるモデルの各プロパティのフォームフィールドがあることも確認してください。私の例ではRazorもBTWを使用しています。

+0

私の編集を見てください。 – rebelliard

+0

OK今はどういう意味か分かります。私は同じ問題が私の最後のプロジェクトを思い付いていた。残念なことに、HTTPポストを使用することは、本質的にモデルをキーと値のペアに相当するものに制限することになります。つまり、プロパティーがコントローラーに戻されるたびに、より多くのビジネス・オブジェクトを持つ複雑なモデルを作成することはできません。そのため、部門リストを永続的に保管しなければなりません。セッションが完了すると、それをクリアする限り、セッションはこれに適しています。実際には、ワイヤでオブジェクトを送信する必要がある場合は、JSONなどのシリアル化技術を使用する必要があります。 – jhsowter

+0

私は参照してください。隠し入力またはSession []オブジェクト内のJSONからデータを戻すことをお勧めしますか?ありがとう。 – rebelliard

0

MVCでOrderウィザードを作成しようとしたときに同様の問題が発生しました(ウィザードの各ページがAJAXによって読み込まれる部分的なビューとして実装されています)。私の場合は、ウィザードでこれをやっていたので

public Order MergeChanges(Order newOrder) 
{ 
    var sessionHistory = (List<string>)Session["sessionHistory"]; 

    if (sessionHistory == null || sessionHistory.Count == 0) 
    return MergeChanges(newOrder, -1); 

    return MergeChanges(newOrder, MasterViewController.GetStepNumberByName(sessionHistory.Last())); 
} 

public Order MergeChanges(Order newOrder, int step) 
{ 
    PreMerge(newOrder); 

    Order result = null; 
    try 
    { 
     ApplyLookups(ref newOrder); 
     Order oldOrder = (Order)Session["order"]; 

     if (oldOrder == null) 
     { 
      Session["order"] = newOrder; 
      result = newOrder; 
     } 
     else 
     { 
      List<TypeHelper.DecoratedProperty<ModelPageAttribute>> props = null; 
      newOrder.GetType().GetDecoratedProperty<ModelPageAttribute>(ref props); 
      props = props.Where(p => (p.Attributes.Count() > 0 && p.Attributes.First().PageNumber.Contains(step))).ToList(); 
      foreach (var propPair in props) 
      { 
       object oldObj = oldOrder; 
       object newObj = newOrder; 
       if (!string.IsNullOrEmpty(propPair.PropertyPath)) 
       { 
        bool badProp = false; 
        foreach (string propStr in propPair.PropertyPath.Split('\\')) 
        { 
         var prop = oldObj.GetType().GetProperty(propStr); 
         if (prop == null) 
         { 
          badProp = true; 
          break; 
         } 

         oldObj = prop.GetValue(oldObj, BindingFlags.GetProperty, null, null, null); 
         newObj = prop.GetValue(newObj, BindingFlags.GetProperty, null, null, null); 
        } 
        if (badProp) 
          continue; 
       } 

       if (newObj == null) 
        continue; 

       var srcVal = propPair.Property.GetValue(newObj, BindingFlags.GetProperty, null, null, null); 
       var dstVal = propPair.Property.GetValue(oldObj, BindingFlags.GetProperty, null, null, null); 

        var mergeHelperAttr = propPair.Property.GetAttribute<MergeHelperAttribute>(); 
        if (mergeHelperAttr == null) 
        { 
         if (newObj != null) 
          propPair.Property.SetValue(oldObj, srcVal, BindingFlags.SetProperty, null, null, null); 
        } 
        else 
        { 
         var mergeHelper = (IMergeHelper)Activator.CreateInstance(mergeHelperAttr.HelperType); 
         if (mergeHelper == null) 
          continue; 

         mergeHelper.Merge(context, HttpContext.Request, newObj, propPair.Property, srcVal, oldObj, propPair.Property, dstVal); 
        } 
       } 
       result = oldOrder; 
      } 
    } 
    finally 
    { 
    PostMerge(result); 
    } 
    return result; 
} 

、唯一の特定:私は非常にそれが方法を提案したが、これを解決するための私の方法は、私のウィザードによって呼び出される各アクションでカスタムMergeChangesメソッドを呼び出すことだったある疑問ウィザードの現在のページに知られた特性のための唯一の口座に順番になるよう、各ページに適用される値は、私はいくつかの属性、(確かに複雑なオーバー)ViewController層、およびカスタム検証層を実装しました。私はいくつかのコードを共有することができますが、上記のコードは、複雑な状況にない場合には不平等な作業を行います。より良い方法があれば、私はこれはPITAだったので、この質問への回答から、それを学ぶことを願っています。

+0

うわー。あなたの答えに感謝します。私はJSONでhiddensの値を保存してから読み直すことを考え始めました。何かご意見は? – rebelliard

+0

Webアプリケーションの動作可能な要件によって異なります。それは本当に汚いと感じるし、大きなフィールドセットを持っていれば、これは重くなる可能性があります。しかし、それはおそらく動作します。私の場合、150以上の複雑なダイナミックフィールドが考慮されていたので、実際には選択肢にはなりませんでした。あなたがより良い解決策を見つけることを願っています。 –

0

私はこの質問は、より頻繁に起動しない驚いて、私も明らかに(私見)答えを驚かせていますが、これらの日の標準的な使い方ではありません。ほぼすべてのポストは、Ajaxベースでなければなりません。これにより、さまざまな問題が解決されます。

  1. フォームデータを再作成する必要はありません。検証エラー、またはアプリケーションエラー(例外)です。これは、クライアント側の状態(真のリッチWebアプリケーションの仕方)がある場合に特に望ましいことです。
  2. クライアント側の検証を強制する必要はありません。検証は100%サーバー側(はとにかくである必要があります)、ユーザーエクスペリエンスはほぼ同じです。もちろん

は、あなたがこのためのフレームワークを構築するために必要ないくつかの初期の作品があり、例えば、私は、JSONをレンダリングAjaxUpdate、AjaxNothing、AjaxRedirect、AjaxErrors ...のActionResult型のセットを持っていますカスタムJavascriptで処理されます。しかし、一度それを取得すると、滑らかなセーリングです。

+0

'検証は100%サーバー側(どこにでもある必要があります)'にすることができます。私はMSが 'DataAnnotation'を押すことで*クライアント側の検証にもっと傾いているという印象を受けました。実際に何が起こっているのかを実際に理解するのに十分な時間を費やさなかったのですが、MVC3や検証で見つけたチュートリアルはすべて、「Unobtrustive Javascript」/ DataAnnotationのアプローチを推進するようです。何か不足していますか? –

+0

@ M.Babcock - 私はMSがDataAnnotationsと "Unobtrusive Javascript"を使って何をしようとしているのかは、クライアントサイドとサーバサイドの重複した検証の問題を解決することであると思います。 *サーバー側とクライアント側の両方の検証を透過的に実行しますが、いずれの場合もサーバー側の検証は信頼できるものであり、クライアント側の検証はユーザーエクスペリエンスのみに適用されます。しかし、私の解決策は問題を完全に取り除いています(私が主張している問題は時代遅れです)。 –

+0

@M。Babcock - 私はまだDataAnnotationsを使用していますが(私はFluentValidationを最近使用しています)、検証サーバー側を実行し、Ajax onsuccessコールバックによってJavascriptでレンダリングされるAjaxErrors Jsonレスポンスでエラーを返します。 –

関連する問題