2012-04-23 9 views
2

コントローラに返す必要があるデータ行がいくつかあるテーブルがあります。私の見解では、まず期間を選択してボタンをクリックしてテーブルをロードします。テーブルに関連するすべてのレコードがロードされますが、テーブルセルの1つにドロップダウンリストが含まれています。だから、ドロップダウンで「更新」をクリックすると、変更が保存されます。MVC:複数行のデータをコントローラに返す

私は試して保存するまですべてが機能します。コントローラに送信されるモデルは完全にnullです。私はテーブルのセルに結び付けているリストのプロパティは、コントローラのnullに戻ります。

@ModelType SuperViewModel 
//We need this a view model in order to store a List of the models in the table 

@Using (Html.BeginForm()) 
@For Each i in Model.CompleteList 
    Dim currentItem = i //MVC auto-generated extra declarations. Seems redundant to me but it works. 
@<table> 
<tr> 
<td>@Html.DisplayFor(function(Model)currentItem.Name)</td> 
<td>@Html.DisplayFor(function(Model)currentItem.SampleTime)</td> 
<td>@Html.DropDownListFor(function(Model)currentItem.WorkTime, ViewBag.WorkTimeList)</td> 
</tr> 
Next 
</table> 
<input name="submit" type="submit" value="Update"/> 
End Using 

//Controller 
<HttpPost()> 
function Save(vmodel as SuperViewModel, submit as String) as ActionResult //NOTE: submit parameter is used because we have two submit buttons but its not relevant here 
     if submit = "Update" 
      db.Entry(vmodel.CompleteList).State = EntityState.Modified//Here the exception is throw because our list is null at this point even tho its tied to the model in the view. 
      db.SaveChanges() 
     end if 
End Function 

注:これはVB.NETで書かれていますが、C#のヘルプは大歓迎です。私はMVCの両方の言語に精通しています。

+0

SuperViewModelはどのように定義されていますか? –

+0

それにはいくつかのプロパティがありますが、ここで適用されるものはList(Of AnotherModel)である "CompleteList"です。その他のモデルは、私たちのDBテーブルに基づいてEntity Frameworkによって生成されました。 – ExceptionLimeCat

+0

'For Each'を閉じるために' End Using'の前に 'Next'がありませんか?また、ビューでレンダリングされたマークアップの一部を追加できますか? –

答えて

2

イテレータにはaを使用し、HTML要素にはインデックス付き要素を使用する必要があります。私はVB.NETの構文を知らない、C#の例は以下のとおりです。これにより、モデルバインダーは、ビューモデルの要素を正しく決定し、ポストバック時にビューモデルを再作成できるようになります。

<table> 
@For(var i = 0; i < Model.CompleteList.Count; i++) 
{ 
<tr> 
<td>@Html.DisplayFor(Model.CompleteList[i].Name)</td> 
<td>@Html.DisplayFor(Model.CompleteList[i]..SampleTime)</td> 
<td>@Html.DropDownListFor(Model.CompleteList[i]..WorkTime, ViewBag.WorkTimeList)</td> 
</tr> 
} 
</table> 

あなたのポスト方法はうまくいくはずです。

+0

これは正しいです。われわれの列を特定のインスタンスにバインドしていない。ありがとう。 – ExceptionLimeCat

0

パラメータ名にいくつかの競合があるため、nullが返される可能性があります(使用されるパラメータ名には、他にも何かを使用する必要があります)。私はDropDownListForによって生成されたマークアップに名前を確認する必要があるでしょうが、私はcurrentItemであなたがCompleteListタイプに対して結合されているので、それは疑うこの

<input name="subButton" type="submit" value="Update"/> 

function Save(vm as SuperViewModel, subButton as String) as ActionResult 
+0

それはうまくいかなかった。 SuperViewModelは、コントローラに当たったときでもまだnullです。 – ExceptionLimeCat

+0

これを参照してください[ブログの投稿](http://codeblog.shawson.co.uk/mvc-strongly-typed-view-returns-a-null-model-on-post-back/) –

+0

そのブログはしませんでした本当に助けてください。 ModelState検証を追加しました。ビューモデルがまだヌルである場合は、それを渡します。 – ExceptionLimeCat

0

を変更してみてください、しかし、あなたのコントローラーメソッドは完全なSuperViewModelタイプを予期しています。あなたがSuperViewModelのタイプにバインドしていることがわかっていることは、コードのどこにも示されていません。

にあなたのコントローラメソッドを変更してみてください:

<HttpPost()> 
function Save(currentItem as CompleteList, submit as String) as ActionResult //NOTE: submit parameter is used because we have two submit buttons but its not relevant here 
     if submit = "Update" 
      db.Entry(vmodel).State = EntityState.Modified//Here the exception is throw because our list is null at this point even tho its tied to the model in the view. 
      db.SaveChanges() 
     end if 
End Function 

WorkTimeプロパティは、DropDownListコントロールから選択した値を移入する必要があります。

編集:は、バインディング名と一致するようにパラメータ名を変更しました。

+0

これはドロップダウンリストのタグです。 'For Each'以下の2番目の宣言がMVCにモデルへのバインディングを認識させないと言っていますか? – ExceptionLimeCat

+0

興味深い。私はモデルバインディングのVB版に慣れていませんが、モデルバインダーがコントローラのパラメータに値をマップすることができないため、Nothing(またはnulls)を取得する理由があります。モデルが 'currentItem As CompleteList'と呼ばれるものにマップすることを期待しているように見えます。 – mgnoonan

関連する問題