Note that there are some explanatory texts on larger screens.

plurals
  1. POMVC dbContext find parent record when current record has no elements
    primarykey
    data
    text
    <p>I'm a MVC/C# beginner so go easy.</p> <p>I have an existing database where a Customer has zero or many Projects. I've built an ASP.Net project from ADODB Entity data model and dbContext code generators.</p> <p>I have a customer: Joe Bloggs (ID=7). I click on the 'Projects' link for Joe Bloggs in my form to see his projects. He doesn't have any. I want to create a project for him so I call the Create action on the project controller.</p> <p>I need to pass Joe Bloggs ID to the Create action for three reasons (which may not be necessary - please enlighten me if need be)</p> <ol> <li><p>Because this is a project for Joe Bloggs I need to pass ID=7 into the controller so I can set the default Customer ID for him when generating the model data for the create view</p></li> <li><p>When I hit the Cancel button on the Create view, I want to go back to the originally filtered view of projects based on Joe Blogs</p></li> <li><p>When I hit save I want to got back to the originally filtered view of projects based on Joe Bloggs.</p></li> </ol> <p>Anyway if I <em>do</em> have one or more projects for Joe Bloggs then I can use this monster below to access his id from the model data within the view:</p> <pre><code>&lt;input type="button" title = "New Project" value="New Project" onclick="location.href='@Url.Action("Create", new { id = Model.First().Customer_ID })'" /&gt; </code></pre> <p>Here is the issue: if he doesn't have any projects, Model.First() doesn't return anything so I can't find the 'parent' Customer_ID record.</p> <p>I used dbContext to generate the model classes (this is a data-first development). Something tells me I could extend these classes or create a new class to allow for the case above.</p> <p>My current workaround is to use ViewBag to pass the various id's and strings from viewer > controller like a hot potato but this means if get three deep (Customer > Proejct > Task), and I want to display the customer name on the task, I've passed it twice. It smells.</p> <p>I notice that the drop down in the Project Index view <strong>has the Customer in it</strong>. Here is my code for that:</p> <pre><code>@Html.DropDownList("Customer_ID", null, "Select a Customer to Filter", new { @onchange = "this.form.submit();" }) </code></pre> <p>I might be able to hack it out of there but really I want to be able to traverse up from a class which might be two or three deep and far removed from this drop down</p> <p>Here is an abridged Customer and CustomerProject class generated from dbContext</p> <pre><code>public partial class Customer { public Customer() { this.Tasks = new HashSet&lt;Task&gt;(); this.CustomerProjects = new HashSet&lt;CustomerProject&gt;(); } public int Customer_ID { get; set; } public string Customer_Name { get; set; } public virtual ICollection&lt;CustomerProject&gt; CustomerProjects { get; set; } } public partial class CustomerProject { public CustomerProject() { this.Tasks = new HashSet&lt;Task&gt;(); this.CustomerProjectTasks = new HashSet&lt;CustomerProjectTask&gt;(); } public int CustomerProject_ID { get; set; } public int Customer_ID { get; set; } public string Project_Name { get; set; } public virtual ICollection&lt;Task&gt; Tasks { get; set; } public virtual Customer Customer { get; set; } public virtual ICollection&lt;CustomerProjectTask&gt; CustomerProjectTasks { get; set; } } </code></pre> <p>I'm sure there is an obvious solution but my strength is in databases and VB6, not C#</p> <p>At Mystere Man's suggestion I have built a ViewModel class, but I'm having a little trouble:</p> <p>Here is what's in my model class file (as I understand it this is just a wrapper around the the existing project entity):</p> <pre><code>namespace zzz.Models { using System; using System.Collections.Generic; public class ProjectsViewModel { public int Customer_ID { get; set; } public ICollection&lt;CustomerProject&gt; CustomerProjects; } } </code></pre> <p>Here's whats in the Index action of my controller (I havejust added my existing Project collection to the new ViewModel class):</p> <pre><code> public ViewResult Index(int pCustomer_ID = 0, string pProjectName_Filter = "") { // Set up drop down ViewBag.Customer_ID = new SelectList(db.Customers.OrderBy(x =&gt; x.Customer_Name), "Customer_ID", "Customer_Name"); //ViewBag.Selected_Customer_ID = Customer_ID; // If no parameters entered, show nothing // Otherwise optionally filter each parameter var projects = from p in db.CustomerProjects orderby p.Active, p.Project_Order where (p.Project_Name.Contains(pProjectName_Filter) || pProjectName_Filter.Equals("")) &amp;&amp; (p.Customer_ID == pCustomer_ID || pCustomer_ID.Equals(0)) &amp;&amp; !(pCustomer_ID.Equals(0) &amp;&amp; pProjectName_Filter.Equals("")) select p; var customerprojects = new ProjectsViewModel { Customer_ID = pCustomer_ID, CustomerProjects = projects.ToList() }; return View(customerprojects); } </code></pre> <p>Here's an extract from my view (I have tried to iterate through the Project collection within the ViewModel class):</p> <pre><code>@model IEnumerable&lt;BistechPortal.Models.ProjectsViewModel&gt; &lt;table&gt; @foreach (var item in Model.CustomerProjects) { &lt;tr&gt; &lt;td&gt; @Html.DisplayFor(modelItem =&gt; item.Project_Name) &lt;/td&gt; &lt;/tr&gt; } &lt;/table&gt; </code></pre> <p>When I run the Index action, on the foreach line I get:</p> <pre><code>'System.Collections.Generic.IEnumerable&lt;zzzzPortal.Models.ProjectsViewModel&gt;' does not contain a definition for 'CustomerProjects' " </code></pre> <p>Please translate - why can't it find my 'CustomerProjects' collection inside my ViewModel?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload