文字列値を持つFoo
を含むBar
クラスを持つモデルオブジェクト構造があります。
public class Foo
{
public Bar Bar;
}
public class Bar
{
public string Value { get; set; }
}
そして、このような構造を使用するビューモデル
public class HomeModel
{
public Foo Foo;
}
次に、Razorで次のようなフォームが表示されます。
<body>
<div>
@using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
<fieldset>
@Html.TextBoxFor(m => m.Foo.Bar.Value)
<input type="submit" value="Send"/>
</fieldset>
}
</div>
</body>
Htmlになります。
<form action="/Home/Save" method="post">
<fieldset>
<input id="Foo_Bar_Value" name="Foo.Bar.Value" type="text" value="Test">
<input type="submit" value="Send">
</fieldset>
</form>
最後に、このようにポストルーを処理するコントローラー
[HttpPost]
public ActionResult Save(Foo foo)
{
// Magic happends here
return RedirectToAction("Index");
}
私の問題は、Bar
のFoo
がnull
コントローラーアクションにヒットするとSave
になるということです(Foo
は作成されますが、null
Bar
フィールド)。
MVCのモデルバインダーはFoo
およびBar
オブジェクトを作成し、上記のように見える限りValue
プロパティを設定できると考えました。私は何が欠けていますか?
また、ビューモデルが少し複雑すぎて簡単かもしれないことも知っていますが、私がやろうとしていることに対して、より深いオブジェクト構造を使用できれば本当に助けになります。上記の例ではASP.NET 5を使用しています。
まず、DefaultModelBinder
はフィールドにバインドされないため、プロパティを使用する必要があります
public class HomeModel
{
public Foo Foo { get; set; }
}
第二に、ヘルパーはHomeModel
に基づいてコントロールを生成していますが、Foo
にポストバックしています。 POSTメソッドを
[HttpPost]
public ActionResult Save(HomeModel model)
またはBindAttribute
を使用してPrefix
を指定します(これにより、ポストされた値からプレフィックスの値が実質的に取り除かれます。したがって、Foo.Bar.Value
はバインディングの目的でBar.Value
になります)
[HttpPost]
public ActionResult Save([Bind(Prefix="Foo")]Foo model)
また、メソッドパラメータにプロパティの1つと同じ名前を付けないでください。そうしないと、バインドが失敗し、モデルがnullになります。
これが起こる別の理由を発見しました。それは、プロパティの名前がSettings
である場合です!次のビューモデルを検討してください。
public class SomeVM
{
public SomeSettings DSettings { get; set; } // named this way it will work
public SomeSettings Settings { get; set; } // property named 'Settings' won't bind!
public bool ResetToDefault { get; set; }
}
コードでは、Settings
プロパティにバインドすると、バインドに失敗します(投稿時だけでなく、フォームの生成時でも)。 Settings
の名前をDSettings
(など)に変更すると、突然再び機能します。
私は同じ問題を抱えていたので、@ Stephen Mueckeの手順に従った後、ここでわかるように、入力が無効になっている(ドキュメントのJQueryで無効にしている)ために問題が発生していることに気付きました: ASP.NET MVCで無効な入力を送信するにはどうすればよいですか? 最後に、無効な属性の代わりに読み取り専用を使用し、すべての値がコントローラーに正常に送信されました。
私は同じ問題を抱えていましたが、一度外部キーの隠しフィールドを作成すると...すべてうまくいきました...
フォームの例:
@using (Html.BeginForm("save", "meter", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => Model.Entity.Id)
@Html.HiddenFor(model => Model.Entity.DifferentialMeter.MeterId)
@Html.HiddenFor(model => Model.Entity.LinearMeter.MeterId)
@Html.HiddenFor(model => Model.Entity.GatheringMeter.MeterId)
... all your awesome controls go here ...
}
アクションの例:
// POST: /Meter/Save
[HttpPost]
public ActionResult Save(Meter entity)
{
... world-saving & amazing logic goes here ...
}