asp.net MVC:埋め込みオブジェクトの編集
-
05-07-2019 - |
質問
オブジェクトAのインスタンスをオブジェクトB内に埋め込みます。オブジェクトBのフォームをレンダリングするアクションビューと編集ビューが既にあります。Bを受け入れる強く型付けされた部分ビューにしました。
現在、作成アクションを扱っているので、b = new B(); b.A = new A();
ここで、Bのフォームをレンダリングし、Aの部分ビューを呼び出して、b.Aを渡します。
しかし、返されるのはFormCollection、またはBフィールドがnullに設定された新しいAオブジェクトです。 最初の場合はすべて順調ですが、フォームが検証に失敗した場合はどうすればよいですか?間違ったデータを使用してオブジェクトを手動で作成し、無効なModelStateで再度渡す必要がありますか? 2番目のオプションは可能ですか?
または、ネストされたビューを避ける必要がありますか?別の方法として、AとBの両方のすべての値を持つフォームを処理するために特別なモデルオブジェクトを作成し、このフォームが検証されるときにAとBオブジェクトを手動で入力して保存することを考えました。 。これが唯一の解決策ですか?
解決
説明したようにAとBを使用できるはずです。
次のものがあるとします:
public class B {
public A A {get; set;}
public string X {get; set;}
public int Y {get;set;}
}
public class A {
public string Z {get; set;}
}
//then in your controller:
public ActionResult Edit () {
return View (
new B {
A = new A { Z = "AyyZee" } ,
X = "BeeEcks",
Y = 7
} );
}
つまり、モデルはBのインスタンスです。
ビューとネストされた部分ビューは、次のようなHTMLを生成する必要があります。
<input type="text" name="A.Z" value="AyyZee" />
<input type="text" name="X" value="BeeEcks" />
<input type="text" name="Y" value="7" />
これで、デフォルトのモデルバインダーがこれをフックできるようになります。
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Edit (B input) {
// apply changes
//the binder should have populated input.A
}
これは、AとBの両方にデフォルトのコンストラクタがあり、比較的単純なクラスである場合にのみ機能することに注意してください。もっと複雑なものがある場合は、独自のバインダーを使用できます。
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Edit ( [ModelBinder( typeof( BBinder ) )] B input) {
//...
}
public class BBinder : IModelBinder
{
public object BindModel( ControllerContext controllerContext, ModelBindingContext bindingContext )
{
return
new B {
A = new A { Z = Request["A.Z"] } ,
X = Request["X"],
Y = int.Parse(Request["Y"])
};
}
}
他のヒント
AとBを組み込む独自のカスタムモデルを作成し、そのモデルからビューを作成します フォームを送信すると、カスタムモデルを更新し、個々のモデルを更新/追加できます。
public class CustomViewModel
{
public ModelA myAModel {get;set;}
public ModelB mybModel {get;set;}
}
そのモデルのビューは、AとBを組み込むフォームを作成し、それを可能にします 投稿されたフォームコレクションを使用して、個々のモデルごとに値を設定し、更新/作成してから分離できます。
このコードに関する私の問題は、モデルクラスにある2つのことが原因です。
- フィールドは通常のフィールドではなくプロパティでなければなりません
- 内部オブジェクトを初期化するコンストラクターが欠落していました
したがって、上記のソリューションのクラスは次のようになります。
public class B {
public A a {get; set;}
public string x {get; set;}
public int y {get;set;}
public B() {
a = new A();
}
}
public class A {
public string z {get; set;}
public A() {}
}