2012-04-06 8 views
3

Ich versuche DropDropList mit zwei Fremdschlüssel, die ModelId und CategoryId sind, zu verwenden. Und ich benutze ViewBag mit selectList.ViewBag mehrere SelectList für Dropdown-Liste

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); 
    } 

Und hier ist meine 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> 

Wenn ich Taste einreichen, Fehler kommen, ‚Ein Element mit dem gleichen Schlüssel bereits hinzugefügt wurde‘ Was Problem ist? Ist es ein Problem mit Model?

Hier sind meine Modelle.

--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>(); 
    } 
} 

Wo ist es falsch? Die Indexseite in Create kann Kategorendaten und Modelldaten abrufen. Wenn ich es jedoch übermittele, hat es einen Fehler: "Ein Element mit demselben Schlüssel wurde bereits hinzugefügt". Können Sie mir helfen, wo das Problem ist? Danke.

--added mehr coding--

ich diese LINQ verwenden. Wahrscheinlich hat hier ein Problem.

Wie kann ich 'Model' Entity hier hinzufügen?

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

Ich fügte eine detaillierte Antwort, wie es gemacht werden könnte. –

Antwort

2

Dies ist, wie ich es getan hätte ..

Ich würde vorschlagen, dass Sie nicht Ihre Domain Modelle zur Ansicht schicken zu tun, sondern vielmehr ein Ansichtsmodell für jede Ansicht erstellen. Auf diese Weise fügen Sie nur das ein, was auf dem Bildschirm benötigt wird.

Erstellen Sie eine neue Ansicht Modell für Ihre erstellen Ansicht:

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; } 
} 

Kategorie Klasse:

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

Modellklasse:

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

Ihrer Ansicht erstellen Sie würde die folgende :

@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 --> 
} 

Ihre Aktion Methoden erstellen:

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 
} 

ich auch, dass Sie AutoMapper die Zuordnungen für Sie zwischen Ihrem Domain-Modell und View-Modell zu tun, verwenden würde empfehlen. Ich würde auch empfehlen, dass Sie auf Fluent Validation schauen, um auf Ihre Sichtmodellvalidierungen aufzupassen.

Ich hoffe, das hilft.

AKTUALISIERT ANTWORT

Der Dienst, der verwendet wurde, alle Kategorien könnte wie folgt aussehen zu bekommen:

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 von Autofac injiziert wird.

Kategorie Service-Schnittstelle:

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

ich zum ersten Mal Entity Framework 4.1 Code verwenden derzeit noch.

Meine Kategorie Repository:

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

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

Meine Kategorie Repository-Schnittstelle:

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

Vielen Dank für Ihre Antwort. Kennen Sie ein Beispiel für ViewModel? Ich denke, ich muss ViewModel mehr Details kennen. Wenn Sie einige Websites kennen, lassen Sie es mich wissen. Ich konnte ViewModel nicht richtig verstehen. Wenn Sie ein ViewModel-Tutorial kennen, lassen Sie es mich bitte wissen. Vielen Dank! – wholee1

+0

Mein Vergnügen. Google es einfach. Im Grunde enthält ein Ansichtsmodell nur die Felder, die Sie in Ihrer Ansicht verwenden möchten. Wenn Sie beispielsweise einen neuen Benutzer hinzufügen möchten, würden Sie Felder wie Vorname, Nachname und Alter verwenden, anstatt alles in Ihrem Benutzerobjekt zu verwenden . –

+0

Das Feld, was ich hinzufügen möchte, indem Sie ViewModel verwenden, ist dasselbe wie Feldname in der ursprünglichen Entität? Ich versuche ViewModel zu verstehen, wie es funktioniert. In Ihrer Codierung "viewModel.Categories = categoryService.GetAllCategories();" Wie kann ich KategorieService deklarieren? – 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. 
} 

ich Ihre DbSet auf Produkte geändert haben machen es deutlich. So laden Sie alle Referenzen für ein Produkt oder alle Produkte, um über sie zu iterieren.