49

Razor ビューを使用して MVC 3 でドロップダウン リストを作成する方法について、ここで何百もの記事を読んだ後、自分のケースに合うものを見つけることができませんでした。

状況: 最終的に、従業員をデータベースに追加するためのビューを作成しようとしています。

これは、私が使用している .EDMX モデルのイメージです (create() で使用されるテーブル):

ここに画像の説明を入力

目的:

  1. 従業員を作成します (私は Create.cshtml (強く型付けされた) を StaffNotify チェックボックスの部分ビューで作成しました) {作成ビューからの通知部分ビューで別の @model を使用していますが、それが安全かどうかわかりません??? @model ShadowVenue.Models.Employee & @model ShadowVenue.Models.StaffNotify)

  2. StaffTypeId のドロップダウン ボックスを作成します (テーブル "StaffType" (1 対多の関係があります) から [StaffTypeId] 値を挿入しますが、ドロップダウンには [Type] 文字列値が表示されます)。

  3. GenderId のドロップダウン ボックスを作成します (これにより、テーブル "Genders" (1 対多の関係がある) から [GenderId] 値が挿入されますが、[Gender] 文字列値がドロップダウンに表示されます)。

  4. レコードをデータベースに挿入します (StaffId プライマリ キーで 1 対 1 の関係を持つ別のテーブルにスタッフ通知があります)。

このためのコントローラーコードに問題があるようです。

EDMX モデル内でストアド プロシージャを作成する必要があるのか​​、クエリまたはメソッドの構文を考え出す必要があるのか​​ 、どちらが最善の方法なのかわかりません。

これは、Entity Framework モデルを使用した初めての大規模な MVC3 アプリです。

(ソリューションを支援するためにナビゲーション プロパティ名のいずれかを知る必要がある場合は、私に知らせてください。提供します)

4

2 に答える 2

76

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"))

コメントごとに更新

性別については、上記の提案されたビュー モデルでenderTypes がなくてもよい場合は、これを行うこともできます (ただし、考え直して、このサーバー側をビュー モデルで 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

これらのテーブルは、データのセットが頻繁には変更されないが、時々列挙する必要がある場合に使用するのが好きです。

お役に立てれば!

于 2011-03-16T17:39:33.130 に答える
23

実際には、David の解決策は正しいと言わざるを得ませんが、気になるトピックがいくつかあります。

  1. モデルをビューに送信しないでください=>これは正しいです
  2. を作成しViewModel、モデルをメンバーとして含めると、モデルViewModelがビューに効果的に送信されます=> これは悪いことです
  3. 辞書を使用してオプションをビューに送信する=>このスタイルは良くない

では、どうすればより良いカップリングを作成できるでしょうか?

AutoMapperまたはValueInjecterのようなツールを使用して、ViewModelと Model の間をマッピングします。AutoMapperより良い構文と感触を持っているようですが、現在のバージョンには非常に深刻なトピックがありません:ViewModelモデルからモデルへのマッピングを実行できません (フラット化などの特定の状況下では、これはトピックから外れています)。現在、私は を使用することを好みます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検証が失敗した場合は、事後操作に入るとこの項目が null になるため、SelectListを再入力することを忘れないでください。そのため、私はこれらの人口を関数に分離する傾向があります。return new View(viewModel)何かあったら折り返し電話するだけです。MVC3 によって検出された検証エラーは、ビューに自動的に表示されます。

独自の検証コードがある場合は、所属するフィールドを指定して検証エラーを追加できます。ドキュメントをチェックしModelStateて、それに関する情報を入手してください。

有効な場合viewModelは、次の手順を実行する必要があります。

新しいアイテムの作成の場合は、 からモデルを作成する必要がありますviewModel(最も適しているのは ですValueInjecter)。その後、その型の EF コレクションに追加して、変更をコミットできます。

更新がある場合は、現在のデータベース項目を最初にモデルに取得します。次に、値をviewModel後ろからモデルにコピーできます ( ValueInjectergets を使用すると、非常に迅速に実行できます)。その後、できるようSaveChangesになり、完了です。

ご不明な点がございましたらお気軽にお尋ねください。

于 2011-03-16T18:29:49.127 に答える