0

I have a Microsoft SQL Server database designed as follows: a table Oeuvre, another table Materiau, and finally as I'm in a many-to-many relationship, a table Oeuvre_Materiau.

I'm using Visual Studio 2017, and creating a new project following the basic tutorial that can be found here: https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/database-first-development/

Everything is going fine, my DB design is going fine, and Visual Studio is, I think, understanding correctly how my DB is designed, as we can see here:

enter image description here

VS, being smart, understands that the table Oeuvre_Materiau is just a link between the two tables.

Now, and it may be were I'm going wrong, but I'm generating the controller and the views as the tutorial tells me, by creating a scaffolded item.

OK, we have our view, I can create and edit things and my oeuvre table is populated as should be, everything is fine and dandy (don't worry about the other xxx_ID, those a for a one to one relationship and work as intended) :

enter image description here

Now, I'm trying to add a DropDown menu with the materiau_name defined in my materiau table.

Each oeuvre item can have multiple materiau_name, and these materiau-name elements are defined in my table materiau, hence the table oeuvre_materiau in between comprised of only 2 elements, materiau_id and oeuvre_id.

But I have no clue on how to do that. I tried to add in my view an element from the table materiau, but I just can't find how, and the only model called in my view is the Oeuvre model.

Here is the Oeuvre model class:

namespace WebApplication8.Models
{
    using System;
    using System.Collections.Generic;

    public partial class oeuvre
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public oeuvre()
        {
            this.materiau = new HashSet<materiau>();
        }

        public int oeuvre_id { get; set; }
        public Nullable<System.DateTime> created_on { get; set; }
        public Nullable<bool> is_deleted { get; set; }
        public string titre { get; set; }
        public Nullable<int> annee { get; set; }
        public string emplacement_signature { get; set; }
        public Nullable<int> longueur { get; set; }
        public Nullable<int> largeur { get; set; }
        public Nullable<int> hauteur { get; set; }
        public string historique { get; set; }
        public Nullable<int> categorie_id { get; set; }
        public Nullable<int> lieu_id { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<materiau> materiau { get; set; }
    }
}

The materiau model class:

namespace WebApplication8.Models
{
    using System;
    using System.Collections.Generic;

    public partial class materiau
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public materiau()
        {
            this.oeuvre = new HashSet<oeuvre>();
        }

        public int materiau_id { get; set; }
        public string materiau_name { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<oeuvre> oeuvre { get; set; }
    }
}

The oeuvresController:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using WebApplication8.Models;

namespace WebApplication8.Controllers
{
    public class oeuvresController : Controller
    {
        private CatalogueEntities db = new CatalogueEntities();

        // GET: oeuvres
        public ActionResult Index()
        {
            return View(db.oeuvre.ToList());
        }

        // GET: oeuvres/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            oeuvre oeuvre = db.oeuvre.Find(id);

            if (oeuvre == null)
            {
                return HttpNotFound();
            }
            return View(oeuvre);
        }

        // GET: oeuvres/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: oeuvres/Create
        // Afin de déjouer les attaques par sur-validation, activez les propriétés spécifiques que vous voulez lier. Pour 
        // plus de détails, voir  https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "oeuvre_id,created_on,is_deleted,titre,annee,emplacement_signature,longueur,largeur,hauteur,historique,categorie_id,lieu_id")] oeuvre oeuvre)
        {
            if (ModelState.IsValid)
            {
                db.oeuvre.Add(oeuvre);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(oeuvre);
        }

        // GET: oeuvres/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            oeuvre oeuvre = db.oeuvre.Find(id);

            if (oeuvre == null)
            {
                return HttpNotFound();
            }

            return View(oeuvre);
        }

        // POST: oeuvres/Edit/5
        // Afin de déjouer les attaques par sur-validation, activez les propriétés spécifiques que vous voulez lier. Pour 
        // plus de détails, voir  https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "oeuvre_id,created_on,is_deleted,titre,annee,emplacement_signature,longueur,largeur,hauteur,historique,categorie_id,lieu_id")] oeuvre oeuvre)
        {
            if (ModelState.IsValid)
            {
                db.Entry(oeuvre).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(oeuvre);
        }

        // GET: oeuvres/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            oeuvre oeuvre = db.oeuvre.Find(id);

            if (oeuvre == null)
            {
                return HttpNotFound();
            }

            return View(oeuvre);
        }

        // POST: oeuvres/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            oeuvre oeuvre = db.oeuvre.Find(id);
            db.oeuvre.Remove(oeuvre);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

The Index view :

@model IEnumerable<WebApplication8.Models.oeuvre>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.created_on)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.is_deleted)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.titre)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.annee)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.emplacement_signature)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.longueur)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.largeur)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.hauteur)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.historique)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.categorie_id)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.lieu_id)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.created_on)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.is_deleted)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.titre)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.annee)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.emplacement_signature)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.longueur)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.largeur)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.hauteur)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.historique)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.categorie_id)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.lieu_id)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.oeuvre_id }) |
            @Html.ActionLink("Details", "Details", new { id=item.oeuvre_id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.oeuvre_id })
        </td>
    </tr>
}

</table>

The Create view :

@model WebApplication8.Models.oeuvre

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>oeuvre</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })


        <div class="form-group">
            @Html.LabelFor(model => model.titre, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.titre, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.titre, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.annee, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.annee, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.annee, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.emplacement_signature, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.emplacement_signature, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.emplacement_signature, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.longueur, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.longueur, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.longueur, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.largeur, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.largeur, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.largeur, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.hauteur, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.hauteur, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.hauteur, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.historique, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.historique, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.historique, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.categorie_id, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.categorie_id, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.categorie_id, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.lieu_id, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.lieu_id, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.lieu_id, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

The EDIT and DETAIL view are pretty similar.

So, I'm simply trying to add a dropdown box in my different view, which would be populated and populate the linking table oeuvre_materiau:

enter image description here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Adamm94
  • 1
  • 1
  • I'm wondering if a viewmodel can solve my issue ? I'm trying to find a good read on the subject, maybe https://stackoverflow.com/questions/39995841/database-first-and-view-models – Adamm94 May 20 '19 at 14:05
  • Pretty big question. Try to break it into smaller issues. Generally, for many to many you would place a grid or table with a foreach in your view to iterate the related items (Materiau) and then provide buttons to add, edit, remove. Something like [this](https://stackoverflow.com/questions/11139993/net-mvc-master-detail-view-with-associated-records). – Steve Greene May 20 '19 at 17:30
  • A couple of other points. Call your collection `Materiaus` (plural). Then when fetching, make sure you pull the child records in: replace `oeuvre oeuvre = db.oeuvre.Find(id);` with `oeuvre oeuvre = db.oeuvre.Include(o => o.Materiaus).Single(o => o.oeuvre_id == id)` – Steve Greene May 20 '19 at 17:33

0 Answers0