私は現在、多くの類似モデルがあるプロジェクトに取り組んでいます。それらはすべて同じ基本モデルから継承し、基本モデルを処理する共通のコントローラー (リスト、追加、編集などの基本的なもの) も作成しました。それは実際に機能し、物事を簡単にしましたが、ドロップダウンに小さな問題があります.
詳細は省きますが、アクションを使用してコントローラーからビューにデータを渡すことができれば、作業は非常に簡単になります。このようなもの:
@Html.DropDownListFor(model => model.Xtypechild, Action("GetList", "XController"))
アクションGetList
が戻る場所IEnumerable<SelectListItem>
このようにして、コードを 1 回だけ記述して、さまざまなコントローラーに使用することができました。
ばかげているように聞こえるかもしれませんが、これを行うために従来の方法の 1 つを使用しようとすると、コードが再び冗長になり、コントローラーを継承することで得た利点の一部が失われます。
私が今見ることができる唯一の代替手段はGetList
、すべての項目で JSON を返して、Ajax/JS を使用してドロップダウンに入力することです。ドロップダウンを含む部分ビューを返すアクションを作成することもできますが、それが良いアイデアかどうかはわかりません。
すべての入力に感謝します。結局、私は次の解決策に行きました:
モデルのデータベース操作を処理するためのサービス クラスがありました。IEnumerable<SelectListItem>
基本サービス クラスにを生成するメソッドを追加するだけです。ここで、ViewBag を介してドロップダウンの項目を渡します (ただし、ビューで使用する前にそれらを IEnumerable にキャストし直す必要があります)。継承されたコントローラーのオーバーライドされたコンストラクターで、それらを ViewBag に割り当てます。
このソリューションが私たちのプロジェクトに適しているかどうかは、コードの元の作成者に相談するのが最善ですが、彼は現在休暇中です。今のところ、これを行う必要があります。良い面としては、この方法ではコードがほとんど生成されないため、簡単に置き換えることができるはずです (そうする必要がある場合)。
コードが少し進化し、ビューに次のようなものが表示されました (int?
プロパティが int 型であり、それ以外の場合は機能しないため、キャストが存在することに注意してください)。
Html.DropDownListFor(
model => model.XId,
new SelectList((List<X>)ViewBag.Xs, "Id", "Name", (Model != null ? (int?)Model.XId : null)),
" -- select -- ",
null)
そして、コントローラーのオーバーライドされたコンストラクター内で次のようなもの:
ViewBag.Xs = db.Xs.ToList();
かみそりでドロップダウンを実装するのは間違いなく最良の方法ではありませんが、プロジェクトでドロップダウンを実装する最良の方法でした。その理由は、プロジェクトで ViewModel を使用し、ベース コントローラーのすべてのアクションをオーバーライドしてそれらを処理する (およびそれらのアクションのドロップダウンにデータを提供する) 時間がなかったからです。
コードはさらに進化しました。データがほんの一握りのビューで使用される場合、コントローラー コンストラクターでクエリを実行することは確かに良い考えではありません。したがって、コンストラクターには次のものと同等のものが含まれます。
ViewBag.Xs = (IQueryable<X>)db.Xs;
そしてビュー:
Html.DropDownListFor(
model => model.XId,
new SelectList((IQueryable<X>)ViewBag.Xs, "Id", "Name", (Model != null ? (int?)Model.XId : null)),
" -- select -- ",
null)
このようにして、ビューが実際にデータを必要とする場合にのみクエリが実行されます。