1

I have a simple ASP.Net MVC app with Entity Framework 6.

I have two tables: a "Contacts" list (with names, addresses and phone#s) and a second table that records zero or more "Notes" history records for each contact:

Models/Contact.cs:

   public class Contact
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ContactId { get; set; }
        public string Name { get; set; }
        public string EMail { get; set; }
        public string Phone1 { get; set; }
        ...
        public virtual List<Note> Notes { get; set; }
    }

Models/Note.cs:

public class Note
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int NoteId { get; set; }
    public string Text { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime? Date { get; set; }
    [ForeignKey("Contact")]
    public int ContactId { get; set; }
    public virtual Contact Contact { get; set; }
}

I did an "Add Controller" in Visual Studio, which auto-generated "ContactsController.cs" and Views for "Index.cshtml", "Details.cshtml", "Edit.cshtml" and "Delete.cshtml". All the auto-generated code looks good, and runs fine. But it didn't show any "Notes".

I was able to display the "notes" and add links to Edit or Delete a note by adding the following to "Details.cshtml" and "Edit.cshtml":

Views/Contacts/Edit.cshtml:

@model ContactsApp.Models.Contact
...
<h4>Notes</h4>
<table class="table">
    <tr>
        <th>Date</th>
        <th>Note</th>
        <th>&nbsp;</th>
    </tr>

    @for (int i = 0; i < Model.Notes.Count(); i++)
    {
        <tr>
            <td>@Html.DisplayFor(model => model.Notes[i].Date)</td>
            <td>@Html.DisplayFor(model => model.Notes[i].Text)</td>
            <td>
                @Html.ActionLink("Edit Note", "EditNote", new { noteId = Model.Notes[i].NoteId }) |
                @Html.ActionLink("Delete Note", "DeleteNote", new { noteId = Model.Notes[i].NoteId })
            </td>
        </tr>
    }
</table>

I've also created an "EditNote.cshtml" view ... but I haven't been able to figure out how to call it from ContactsController:

Controllers/ContactsController.cs:

   // GET: Contacts/EditNote?noteId=3
    public async Task<ActionResult> EditNote(int? noteId)
    {
        if (noteId == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Note note = await db.Contacts.Where(c => c.Notes.noteId == noteId);
        if (note == null)
        {
            return HttpNotFound();
        }
        return View(note);
    }

Q: What is the correct ASP.Net MV syntax to fetch the "Note" and pass it down to the "EditNote" view?

FoggyDay
  • 11,962
  • 4
  • 34
  • 48

2 Answers2

2

Your code shouldn't normally compile due to the following line:

Note note = await db.Contacts.Where(c => c.Notes.noteId == noteId);

The type of the expression on the right is IEnumerable<Contact>, whereas the type of the variable you assign it is Note. This should change to the following:

Note note = await db.Notes.FirstOrDefaultAsync(note => note.NodeId == noteId);

Btw: Where is a synchronous call, so no need for using the await keyword.

Christos
  • 53,228
  • 8
  • 76
  • 108
  • It *didn't* compile. My question was how to get the syntax for querying the right "Note" with respect to "Contacts". You and Athanasios Kataras pointed me in the right direction: I shouldn't be dealing with "Contacts" at all. If I want a "Note" ... I should simply query the "Notes" table. I did - and it worked :) Thank you! – FoggyDay Nov 18 '19 at 08:19
1

You are returning a Contact.

You should be querying notes and using FirstOrDefault.

db.Notes.Where(n=> n.NoteId =id).FirstOrDefault();

If you want to select from contacts by id and note id for better efficiency, try Using LINQ, select list of objects inside another list of objects

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • Perfect - thank you. My mistake was thinking that I needed to query "Contacts" to find the right "note". I didn't even expose "Notes" in my DBContext class - only "Contacts". And things seemed to work. For awhile, until this problem. So I added Notes to DBContext, I applied the syntax you and Christos gave me (`Note note = db.Notes.FirstOrDefault(n => n.NoteId == noteId);` .. and it's working. Thank you :) – FoggyDay Nov 18 '19 at 08:23
  • Cheers m8! Glad I could help. – Athanasios Kataras Nov 18 '19 at 08:23