2012-04-06 15 views
3

modelIdとcategoryIdの2つの外部キーを持つdropdownListを使用しようとしています。 そして、私はselectListと共にViewBagを使用しています。ViewBag複数のSelectListのドロップダウンリスト

public ActionResult Create() 
    { 
     ViewBag.categoryId = new SelectList(db.Category, "categoryId", "name"); 
     ViewBag.modelId = new SelectList(db.Model, "modelId", "name"); 
     return View(); 
    } 

    // 
    // POST: /Product/Create 

    [HttpPost] 
    public ActionResult Create(Product product) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Product.Add(product); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.categoryId = new SelectList(db.Category, "categoryId", "name", product.categoryId); 
     ViewBag.modelId = new SelectList(db.Model, "modelId", "name", product.modelId); 
     return View(product); 
    } 

ここに私のCreate.cshtmlがあります。

<div class="editor-label"> 
     @Html.LabelFor(model => model.Category) 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownList("categoryId", "--Select--") 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Model) 
    </div> 

    <div class="editor-field"> 
     @Html.DropDownList("modelId", "--Select--") 
    </div> 

私は送信ボタンを押すと、 問題は何か「を同じキーを持つ項目が既に追加されている」、エラーが出てきますか?モデルに問題はありますか?

私のモデルです。

--Prodruct.cs-- 

public class Product 
{ 
    [Key] public int productId { get; set; } 

    [Required(ErrorMessage = "Please select category")] 
    public int categoryId { get; set; } 

    [Required(ErrorMessage = "Please select model")] 
    public int modelId { get; set; } 

    [DisplayName("Model name")] 
    public String model { get; set; } 

    public virtual Category Category { get; set; } 
    public virtual Model Model { get; set; } 
} 

--Category.cs-- 
public class Category 
{ 
    [Key] public int categoryId { get; set; } 
    public String name { get; set; } 
} 

--Model.cs-- 
public class Model 
{ 
    [Key] public int modelId { get; set; } 
    public String name { get; set; } 
} 

--RentalDB.cs-- 
public class rentalDB : DbContext 
{ 
    public DbSet<Product> Product { get; set; } 
    public DbSet<Model> Model { get; set; } 
    public DbSet<Customer> Customer { get; set; } 
    public DbSet<Order> Order { get; set; } 
    public DbSet<Cart> Cart { get; set; } 
    public DbSet<Category> Category { get; set; } 
    public DbSet<OrderDetails> OrderDetails { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
    } 
} 

どこが間違っていますか? CreateのIndexページでカテゴリデータとモデルデータを取得できます。しかし、私がそれを提出すると、 '同じキーを持つアイテムが既に追加されています'というエラーが表示されます。 どこに問題があるのか​​教えてください。 ありがとうございます。

- コーディングがさらに追加されました。

私はこのLINQを使用しています。おそらくここに問題があるでしょう。

ここに「モデル」エンティティを追加するにはどうすればよいですか?これは私がそれを行っているだろうかある

var product = from a in db.Product.Include(a => a.Category) 
         select a; 
+0

どうすればよいのか詳細な回答が追加されました。 –

答えて

2

..

私はあなたがビューにドメインモデルを送信しないことを示唆しているのではなく、各ビューのビューモデルを作成します。このようにすると、必要なものだけが画面に表示されます。

ビュー作成のための新しいビューモデルを作成します。あなたは、次のを持っているでしょう、あなたの作成ビューで

public class Model 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class ProductCreateViewModel 
{ 
    // Include other properties if needed, these are just for demo purposes 

    public string Name { get; set; } 
    public string SKU { get; set; } 
    public string LongDescription { get; set; } 

    // This is the unique identifier of your category, 
    // i.e. foreign key in your product table 
    public int CategoryId { get; set; } 
    // This is a list of all your categories populated from your category table 
    public IEnumerable<Category> Categories { get; set; } 

    // This is the unique identifier of your model, 
    // i.e. foreign key in your product table 
    public int ModelId { get; set; } 
    // This is a list of all your models populated from your model table 
    public IEnumerable<Model> Models { get; set; } 
} 

をCategoryクラス:

public class Category 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

Modelクラスを:

@model MyProject.ViewModels.ProductCreateViewModel 

@using (Html.BeginForm()) 
{ 
    <table> 
      <tr> 
       <td><b>Category:</b></td> 
       <td> 
        @Html.DropDownListFor(x => x.CategoryId, 
         new SelectList(Model.Categories, "Id", "Name", Model.CategoryId), 
         "-- Select --" 
        ) 
        @Html.ValidationMessageFor(x => x.CategoryId) 
       </td> 
      </tr> 
      <tr> 
       <td><b>Model:</b></td> 
       <td> 
        @Html.DropDownListFor(x => x.ModelId, 
         new SelectList(Model.Models, "Id", "Name", Model.ModelId), 
         "-- Select --" 
        ) 
        @Html.ValidationMessageFor(x => x.ModelId) 
       </td> 
      </tr> 
    </table> 

    <!-- Add other HTML controls if required and your submit button --> 
} 

は、あなたのアクションメソッドを作成します。

public ActionResult Create() 
{ 
    ProductCreateViewModel viewModel = new ProductCreateViewModel 
    { 
      // Here you do database calls to populate your dropdowns 
      Categories = categoryService.GetAllCategories(), 
      Models = modelService.GetAllModels() 
    }; 

    return View(viewModel); 
} 

[HttpPost] 
public ActionResult Create(ProductCreateViewModel viewModel) 
{ 
    // Check that viewModel is not null 

    if (!ModelState.IsValid) 
    { 
      viewModel.Categories = categoryService.GetAllCategories(); 
      viewModel.Models = modelService.GetAllModels(); 

      return View(viewModel); 
    } 

    // Mapping 
    Product product = ... // Do your mapping here 

    // Insert product in database 
    productService.Insert(product); 

    // Return the view where you need to be 
} 

私はまた、あなたのドメインモデルとビューモデルの間であなたのためのマッピングを行うためにAutoMapperを使用することをお勧めします。また、あなたのビューモデルのバリデーションの面倒を見るためにFluent Validationを見ることをお勧めします。

こちらがお役に立てば幸いです。

UPDATED ANSWER

すべてのカテゴリは次のようになります取得するために使用されたサービス:

public class CategoryService : ICategoryService 
{ 
    private readonly ICategoryRepository categoryRepository; 

    public CategoryService(ICategoryRepository categoryRepository) 
    { 
      // Check if category repository is not null, throw exception if it is 

      this.categoryRepository = categoryRepository; 
    } 

    public IEnumerable<Category> GetAllCategories() 
    { 
      return categoryRepository.GetAllCategories(); 
    } 
} 

categoryRepositoryはAutofacによって注入されます。

カテゴリーのサービス・インターフェース:

public interface ICategoryService 
{ 
    IEnumerable<Category> GetAllCategories(); 
} 

私は現在、まだ最初のEntity Framework 4.1コードを使用します。

マイカテゴリーリポジトリ:

public class CategoryRepository : ICategoryRepository 
{ 
    MyContext db = new MyContext(); 

    public IEnumerable<Category> GetAllCategories() 
    { 
      return db.Categories 
       .OrderBy(x => x.Name); 
    } 
} 

マイカテゴリーリポジトリインタフェース:

public interface ICategoryRepository 
{ 
    IEnumerable<Category> GetAllCategories() 
} 
+0

返信いただきありがとうございます。あなたはViewModelの例を知っていますか?私はViewModelをもっと知る必要があると思う。あなたがいくつかのウェブサイトを知っているなら、私に知らせてください。 ViewModelについて正しく理解できませんでした。ViewModelチュートリアルが分かっていれば、教えてください。ありがとう! – wholee1

+0

私の喜び。ちょうどGoogleそれ。基本的にビューモデルには、ビューに使用するフィールドのみが含まれています。たとえば、新しいユーザーを追加する場合は、ユーザーオブジェクト内のすべてを使用する代わりに、名、姓、年齢などのフィールドがあります。 –

+0

ViewModelを使用して追加するフィールドは、元のエンティティのフィールド名と同じですか? ViewModelがどのように動作するかを理解しようとしています。あなたのコーディングでは、 'viewModel.Categories = categoryService.GetAllCategories();' categoryServiceはどのように宣言できますか? – wholee1

0
public class Test 
{ 
    rentalDB db = new rentalDB(); 
    public Product LoadProductById(int pId) 
    { 
     return db.Products.Include(p => p.Model).Include(p => p.Category).Where(p => p.productId == pId).SingleOrDefault(); 
    } // To get specific product. 

    public IEnumerable<Product> LoadAllProducts() 
    { 
     return db.Products.Include(p => p.Model).Include(p => p.Category).ToList(); 
    } // To get all products. 
} 

私は製品にごDbSetを変更したが、それがより明確にします。これは、1つの製品またはすべての製品のすべての参照を、それらを反復処理するためにロードする方法です。

関連する問題