3

@ Html.DropDownListFor()を使用しようとする問題が発生しています。コントローラでDropDownListFor&Navigation Properties

public class Thing { 
    ... 
    public virtual Vendor Vendor { get; set; } 
} 

私はViewBagに投げるために、ベンダーのリストをつかんだ:

は、私はそれにナビゲーションプロパティを持つモデルを持っている

public ActionResult Create() { 
    ViewBag.Vendors = Vendor.GetVendors(SessionHelper.CurrentUser.Unit_Id); 
    return View(); 
} 

のHTMLアイテム表示は次のようになります。

@Html.DropDownListFor(model => model.Vendor, new SelectList(ViewBag.Vendors, "Id", "Name"), "---- Select vendor ----") 
@Html.ValidationMessageFor(model => model.Vendor) 

ドロップダウンリストがレンダリングされていて、すべてがうまくいかないようです私はフォームを提出するまで。 ModelState.IsValidでHttpPost Createメソッドがfalseを返してモデルエラーがスローされました:'System.String'型から '... Models.Vendor'型へのパラメータ変換は、型変換器がこれらの型間で変換できないため失敗しました。私は経由ページのポストを聞かせている場合

、私は、サーバーエラーで終わる: 例外の詳細を:System.ArgumentNullException:値をNullにすることはできません。 パラメータ名:items

@ Html.DropDownListFor()がVendorオブジェクトをナビゲーションプロパティに適切に自動バインドしていないという理由を検索できませんでした。

ご協力いただければ幸いです。

EDIT: "Vendor_Id"に直接アクセスできるようにForeignKey属性を明示的に設定しなければならなかったので、ナビゲーションプロパティではなく "Vendor_Id"を指すようにDropDownListForを変更しました。それはうまくいくようです。

答えて

3

私は、これを実行する最良の方法は次のとおりであることを発見しました。 SelectListItemsを作成するようにコントローラーを変更します。次のように

public ActionResult Create() { 
     ViewBag.Vendors = Vendor.GetVendors(SessionHelper.CurrentUser.Unit_Id) 
           .Select(option => new SelectListItem 
           { 
            Text = (option == null ? "None" : option.Name), 
            Value = option.Id.ToString() 
           }); 
     return View(); 
    } 

その後、ビューを変更:

@Html.DropDownListFor(model => model.Vendor, (IEnumerable<SelectListItem>)ViewBag.Vendors, "---- Select vendor ----") 
@Html.ValidationMessageFor(model => model.Vendor) 

をあなたが(IEnumerableを)としてViewBag.Vendorsをキャストする必要があります。

これは、ビューをきれいに整えます。また、SelectListItemsを取得するコードをリポジトリに移動し、GetVendorsList()などのメソッドに入れることもできます。

public IEnumerable<SelectListItem> GetVendorsList(int unitId){ 
    return Vendor.GetVendors(unitId) 
           .Select(option => new SelectListItem 
           { 
            Text = (option == null ? "None" : option.Name), 
            Value = option.Id.ToString() 
           }); 
} 

これは懸念を払拭し、コントローラをきれいに保ちます。

幸運

+0

ViewBagをビューデータで渡すようにしてはいけません。あなたはビューモデルを使用します。私はここにコードを投稿することはできません、それは読むことができません。 PM私とあなたに知らせます;) – Ninglin

+0

合意。これはずっと前です。私はMVC 3を中心に考えています。ビューモデルは間違いなく道のりです。 – TheGwa

0

私は以下のstackoverflow質問に同様の質問をしました。答えはこの質問にも良いです。

Validation for Navigation Properties in MVC (4) and EF (4)

このアプローチは、コントローラでSelectListのを公開していません。コントローラのSelectListを公開することは良い考えではないと思います。これはコントローラのビュー部分を管理していることを意味しているため、懸念事項の分離ではありません。