web-dev-qa-db-ja.com

複合オブジェクトおよびモデルバインダーASP.NET MVC

文字列値を持つ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");
}

私の問題は、BarFoonullコントローラーアクションにヒットするとSaveになるということです(Fooは作成されますが、nullBarフィールド)。

MVCのモデルバインダーはFooおよびBarオブジェクトを作成し、上記のように見える限りValueプロパティを設定できると考えました。私は何が欠けていますか?

また、ビューモデルが少し複雑すぎて簡単かもしれないことも知っていますが、私がやろうとしていることに対して、より深いオブジェクト構造を使用できれば本当に助けになります。上記の例ではASP.NET 5を使用しています。

28
Riri

まず、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になります。

38
user3559349

これが起こる別の理由を発見しました。それは、プロパティの名前が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(など)に変更すると、突然再び機能します。

2

私は同じ問題を抱えていたので、@ Stephen Mueckeの手順に従った後、ここでわかるように、入力が無効になっている(ドキュメントのJQueryで無効にしている)ために問題が発生していることに気付きました: ASP.NET MVCで無効な入力を送信するにはどうすればよいですか? 最後に、無効な属性の代わりに読み取り専用を使用し、すべての値がコントローラーに正常に送信されました。

0
joalcego

私は同じ問題を抱えていましたが、一度外部キーの隠しフィールドを作成すると...すべてうまくいきました...

フォームの例:

@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 ...
}

PRETTY PICTURES:
enter image description here

0
Prisoner ZERO