Razorビューを使用してMVC 3でドロップダウンリストを作成する方法についての記事を何百も読んだ後、自分のケースに合ったものが見つかりませんでした。
状況:最終的には、従業員をデータベースに追加するためのビューを作成しようとしています。
これは、私が使用している.EDMXモデルのイメージです(create()で使用されるテーブル)。
目的:
従業員を作成します(StaffNotifyチェックボックスの部分ビューで作成されたCreate.cshtml(厳密に型指定されています)){CreateビューからのNotify部分ビューで別の@modelを使用していますが、それが安全かどうかわかりませんか? @model ShadowVenue.Models.Employeeおよび@model ShadowVenue.Models.StaffNotify)
StaffTypeIdのドロップダウンボックスを作成します(テーブル "StaffType"(1対多の関係)から[StaffTypeId]値を挿入しますが、ドロップダウンに[Type]文字列値を表示します)
GenderIdのドロップダウンボックスを作成します(テーブル "Genders"(1対多の関係)から[GenderId]値を挿入しますが、ドロップダウンに[Gender]文字列値を表示します)
データベースにレコードを挿入します(StaffIdプライマリキーに1対1の関係を持つ別のテーブルにスタッフ通知があります)
私はこのためのコントローラーコードに問題があるようです。
EDMXモデル内にストアドプロシージャを作成する必要があるのか、クエリまたはメソッドの構文を作成するのかはわかりませんが、どちらが最善の方法かわかりません。
これは、Entity Framework Modelを使用した初めての大規模MVC3アプリです。
(ソリューションを支援するためにナビゲーションプロパティ名のいずれかを知る必要がある場合はお知らせください)、提供します)
Dbモデルをビューに直接渡さないでください。 MVCを使用できて幸運なので、ビューモデルを使用してカプセル化します。
次のようなビューモデルクラスを作成します。
public class EmployeeAddViewModel
{
public Employee employee { get; set; }
public Dictionary<int, string> staffTypes { get; set; }
// really? a 1-to-many for genders
public Dictionary<int, string> genderTypes { get; set; }
public EmployeeAddViewModel() { }
public EmployeeAddViewModel(int id)
{
employee = someEntityContext.Employees
.Where(e => e.ID == id).SingleOrDefault();
// instantiate your dictionaries
foreach(var staffType in someEntityContext.StaffTypes)
{
staffTypes.Add(staffType.ID, staffType.Type);
}
// repeat similar loop for gender types
}
}
コントローラ:
[HttpGet]
public ActionResult Add()
{
return View(new EmployeeAddViewModel());
}
[HttpPost]
public ActionResult Add(EmployeeAddViewModel vm)
{
if(ModelState.IsValid)
{
Employee.Add(vm.Employee);
return View("Index"); // or wherever you go after successful add
}
return View(vm);
}
次に、最後にビューで(Visual Studioを使用して最初にスキャフォールドできます)、継承された型をShadowVenue.Models.EmployeeAddViewModelに変更します。また、ドロップダウンリストの場所では、次を使用します。
@Html.DropDownListFor(model => model.employee.staffTypeID,
new SelectList(model.staffTypes, "ID", "Type"))
性別のドロップダウンでも同様です
@Html.DropDownListFor(model => model.employee.genderID,
new SelectList(model.genderTypes, "ID", "Gender"))
コメントごとに更新
性別については、上記の推奨ビューモデルでgenderTypesがなくてもかまいません(ただし、考え直して、このサーバー側をビューモデルでIEnumerableとして生成することもできます)。したがって、以下のnew SelectList...
の代わりに、IEnumerableを使用します。
@Html.DropDownListFor(model => model.employee.genderID,
new SelectList(new SelectList()
{
new { ID = 1, Gender = "Male" },
new { ID = 2, Gender = "Female" }
}, "ID", "Gender"))
最後に、別のオプションはルックアップテーブルです。基本的に、ルックアップタイプに関連付けられたキーと値のペアを保持します。タイプの1つの例としては性別、別の例としては州などが考えられます。
ID | LookupType | LookupKey | LookupValue | LookupDescription | Active
1 | Gender | 1 | Male | male gender | 1
2 | State | 50 | Hawaii | 50th state | 1
3 | Gender | 2 | Female | female gender | 1
4 | State | 49 | Alaska | 49th state | 1
5 | OrderType | 1 | Web | online order | 1
一連のデータがあまり頻繁に変更されないが、それでも随時列挙する必要がある場合に、これらのテーブルを使用するのが好きです。
お役に立てれば!
実は、Davidは彼の解決策にぴったりだと言わざるを得ませんが、私を邪魔するトピックがいくつかあります。
ViewModel
を作成し、ViewModel
にメンバーとしてモデルを含めると、モデルをビューに効果的に送信しました=>これはBADそれでは、どうすればより良い結合を作成できますか?
AutoMapper
または ValueInjecter のようなツールを使用して、ViewModel
とModelの間をマッピングします。 AutoMapper
はより良い構文と感触を持っているようですが、現在のバージョンには非常に厳しいトピックがありません:ViewModel
からModelへのマッピングを実行できません(平坦化などがありますが、これはトピックから外れています)したがって、現時点ではValueInjecter
を使用することを好みます。
そのため、ビューに必要なフィールドを使用してViewModel
を作成します。ルックアップとして必要なSelectListアイテムを追加します。そして、すでにそれらをSelectListsとして追加しています。したがって、LINQ対応のソースからクエリを実行し、IDとテキストフィールドを選択して選択リストとして保存できます。ルックアップとして新しいタイプ(辞書)を作成する必要はなく、_new SelectList
_を移動するだけです。ビューからコントローラーへ。
_ // StaffTypes is an IEnumerable<StaffType> from dbContext
// viewModel is the viewModel initialized to copy content of Model Employee
// viewModel.StaffTypes is of type SelectList
viewModel.StaffTypes =
new SelectList(
StaffTypes.OrderBy( item => item.Name )
"StaffTypeID",
"Type",
viewModel.StaffTypeID
);
_
ビューで呼び出す必要があるのは
_@Html.DropDownListFor( model => mode.StaffTypeID, model.StaffTypes )
_
コントローラーのメソッドのpost要素に戻り、ViewModel
型のパラメーターを取得する必要があります。次に、検証を確認します。検証が失敗した場合、_viewModel.StaffTypes
_ SelectListを再入力することを忘れないでください。この関数はpost関数に入るとnullになるためです。だから私はそれらの人口の事を機能に分離する傾向があります。何か問題がある場合は、return new View(viewModel)
をコールバックするだけです。 MVC3によって検出された検証エラーは、ビューに自動的に表示されます。
独自の検証コードがある場合、それらが属するフィールドを指定することで検証エラーを追加できます。 ModelState
のドキュメントを確認して、その情報を入手してください。
viewModel
が有効な場合、次の手順を実行する必要があります。
新しいアイテムの作成である場合は、viewModel
からモデルを作成する必要があります(ValueInjecter
が最適です)。次に、そのタイプのEFコレクションに追加して、変更をコミットできます。
更新がある場合、最初に現在のデータベース項目をモデルに取得します。その後、viewModel
からモデルに値をコピーして戻すことができます(ここでもValueInjecter
を使用すると、非常にすばやく実行できます)。その後、SaveChanges
を実行できます。
不明な点がある場合はお気軽にお問い合わせください。