0

many-to-manyという名前のメニュー モデルにフィールドがあり、モデルRolesの「作成」ビューを作成しようとしています。

私の作成アクションメソッド:

    public ActionResult Create()
    {
        ViewBag.ParentMenuId = new SelectList(_db.Menus, "Id", "Name");
        ViewBag.Roles = new SelectList(_db.UserRoles.ToList(), "Id", "Name");
        return View();
    }

    [HttpPost]
    public ActionResult Create(Menu menu)
    {
        if (ModelState.IsValid)//the state is always **invalid**
        {
            _db.Menus.Add(menu);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.ParentMenuId = new SelectList(_db.Menus, "Id", "Name", menu.ParentMenuId);
        return View(menu);
    }

私のビュー(Create.cshtml):

    <div class="editor-label">
        @Html.LabelFor(model => model.Roles, "Roles")
    </div>
    <div class="editor-field">
        @Html.ListBox("Roles")
        @Html.ValidationMessageFor(model => model.Roles)
    </div>

それを修正する方法は?次のエラーが表示されます。

The ViewData item that has the key '' is of type '' but must be of type 'IEnumerable<SelectListItem>'

4

2 に答える 2

4

まあ、エラーメッセージはかなり明確です。IEnumerable<SelectListItem>

したがって、ViewBag.Roles の定義を次のように変更します。

new SelectList(_db.UserRoles.ToList(), "Id", "Name");

_db.UserRoles.ToList().Select(m => new SelectListItem { Value=m.Id, Text=m.Name});

編集

あなたの見解では:

@Html.ListBox("Roles", (IEnumerable<SelectListItem>)ViewBag.Roles)

編集2

モデルバインディングの問題があります

あなたの見解では

@Html.ListBox("selectedRoles", (IEnumerable<SelectListItem>)ViewBag.Roles)

ポスト アクションで、新しいパラメータを追加してみてください:

[HttpPost]
    public ActionResult Create(Menu menu, int[] selectedRoles)

選択した各ロールをアクション コードで「手動で」処理します。

編集

ViewModel のサンプル (そのままでは機能しません) ビューでは、

  • DropDownList (ParentMenuId)

  • ListBox (RoleID)

  • この listBox の結果 (ポスト アクションのモデル バインディング)

  • Menu クラスのその他のプロパティ (すべてではないかもしれません)

アイデアは、

public class MenuViewModel 
{
  public IEnumerable<SelectListItem> ParentMenuList {get;set;}//a dropDown
  public IEnumerable<SelectListItem> RoleList {get;set;}//a listBox
  public string Name {get;set;}//the menu name //the menu name
  public List<int> SelectedRoles {get;set;}
}

次に、 get アクションは次のようになります

public ActionResult Create()
{
  var model = new MenuViewModel();
  model.ParentMenuList = new SelectList(_db.Menus, "Id", "Name");
  model.RoleList = new SelectList(_db.UserRoles.ToList(), "Id", "Name");
  return View(model);
}

ビューには MenuViewModel... がモデルとして含まれます

@model MenuViewModel
//your other code
//the listbox
 <div class="editor-label">
        @Html.LabelFor(model => model.SelectedRoles, "Roles")
    </div>
    <div class="editor-field">
        @Html.ListBoxFor(m => m.SelectedRoles, Model.RoleList)
        @Html.ValidationMessageFor(model => model.Roles)
    </div>

次に、あなたの POST アクションは次のようになります

[HttpPost]
public ActionResult Create(MenuViewModel model)
{
    if (ModelState.IsValid)
    {
       var menu = new Menu {Name = model.Name };//for example
       menu.Roles =  _db.UserRoles.Where(rl => model.SelectedRoles.Contains(rl.Id)).ToList();
       _db.SaveChanges();
       return RedirectToAction("Index");
    }
    return View(model);
}

プロ ビューモデル :

  • 必要なプロパティを使用しているだけです。

  • ViewBag は必要ありません (避けるのは良いことです: 動的であり、強く型付けされていないため、テストが難しく、リファクタリングの問題などがあります)。

  • すべてがビューのモデルにあります

短所 ViewModel :

  • get アクションで Model を ViewModel にマップし、Post アクションで ViewModel から Model にマップする必要がありますが、価格はさらに悪いです!
于 2012-10-29T07:45:31.460 に答える
-1

同じプロジェクトを作成しましたが、そのエラーは発生しません。

リストボックスのモデルが別のタイプにバインドされているようです。次のようにビューバッグ モデルを明示的に指定してみてください。

@Html.ListBox("Roles",ViewBag.Roles as SelectList)

[HttpPost] メソッドで、次のように Create - get メソッドに存在する ViewBag.Roles を追加してみてください。

[HttpPost]
    public ActionResult Create(Menu menu)
    {
        if (ModelState.IsValid)//the state is always **invalid**
        {
            _db.Menus.Add(menu);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.ParentMenuId = new SelectList(_db.Menus, "Id", "Name", menu.ParentMenuId);
        ViewBag.Roles = new SelectList(_db.UserRoles.ToList(), "Id", "Name");
        return View(menu);
    }
于 2012-10-29T08:15:59.287 に答える