coolhand coolhand - 3 years ago 131
ASP.NET (C#) Question

MVC Core: Display another property based on primary key

I have a model with a foreign key of another table. In this case, the waiver object is related to an office object

public class Waiver
{
public int WaiverID { get; set; }
[Required(ErrorMessage = "Please select an Office")]
[Range(1, int.MaxValue, ErrorMessage = "Please select an Office")]
public int OfficeID { get; set; }
//...other properties
}


I have a search result that filters by the OfficeID:

IEnumerable<Waiver> waiverList = repository.Waivers
.Where(wl => waiverNum == 0 || wl.WaiverID == waiverNum)
.Where(wl => officeId == 0 || wl.OfficeID == officeId)
//...other search criteria


This is displayed in my View by:

@model IEnumerable<Waiver>

@foreach (var item in Model)
{
<tr>
<td class="text-right">@item.WaiverID</td>
<td class="text-right">@item.OfficeID></td>
@* other display columns *@


While the Waiver object passed to the View has the OfficeID property, I would like to display the Name property in the Office model as it is more useful to the user. How can I accomplish this?

My EF Repository is set up as:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Waiver.Models

//This class implements the IWaiverRepository and gets its data using Entity Framework Core
{
public class EFWaiverRepository : IWaiverRepository
{


private ApplicationDbContext context;

public EFWaiverRepository(ApplicationDbContext ctx)
{
context = ctx;
}


public IEnumerable<Waiver> Waivers => context.Waivers;
public IEnumerable<Office> Offices => context.Offices;

//*****Waiver Methods*****
public void SaveWaiver(Waiver waiver)
{
//if the waiver number is 0, create a new waiver
if (waiver.WaiverID == 0)
{
context.Waivers.Add(waiver);
}
//if there wavier number exists, save the changes to the database
else {
Waiver dbEntry = context.Waivers.FirstOrDefault(w => w.WaiverID == waiver.WaiverID);
if (dbEntry != null)
{
dbEntry.Requestor = waiver.Requestor;
dbEntry.RequestorEmail = waiver.RequestorEmail;
dbEntry.OfficeID = waiver.OfficeID;
dbEntry.RequestDate = waiver.RequestDate;
dbEntry.System = waiver.System;
dbEntry.Source = waiver.Source;
dbEntry.Requirement = waiver.Requirement;
dbEntry.MitigationPlan = waiver.MitigationPlan;
dbEntry.FinalAssessment = waiver.FinalAssessment;
dbEntry.Status = waiver.Status;
//get the signatures
dbEntry.PmSignature = waiver.PmSignature;
dbEntry.PmSignDate = waiver.PmSignDate;
}
}
context.SaveChanges();
}

public Waiver DeleteWaiver(int waiverID)
{
Waiver dbEntry = context.Waivers
.FirstOrDefault(w => w.WaiverID == waiverID);
if (dbEntry != null)
{
context.Waivers.Remove(dbEntry);
context.SaveChanges();
}
return dbEntry;
}

//*****Office Methods*****
public void SaveOffice(Office office)
{
//if the ID=0, its a new entry. Add to db
if (office.OfficeID == 0)
{
context.Offices.Add(office);
} else
{
Office dbEntry = context.Offices.FirstOrDefault(o => o.OfficeID == office.OfficeID);
if (dbEntry != null)
{
dbEntry.Name = office.Name;
dbEntry.SiteID = office.SiteID;
}
}
context.SaveChanges();
}

public Office DeleteOffice(int officeID)
{
Office dbEntry = context.Offices
.FirstOrDefault(o => o.OfficeID == officeID);
if (dbEntry != null)
{
context.Offices.Remove(dbEntry);
context.SaveChanges();
}
return dbEntry;
}


where the EFRepository implements:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Waiver.Models
{
public interface IWaiverRepository
{
IEnumerable<Waiver> Waivers { get; }
IEnumerable<Office> Offices { get; }
IEnumerable<Site> Sites { get; }

void SaveWaiver(Waiver waiver );
Waiver DeleteWaiver(int waiverID);

void SaveOffice(Office office);
Office DeleteOffice(int officeID);
}
}

DSR DSR
Answer Source

Lazy loading is not yet possible with EF Core, so that you need to include related entities. The solution should look like below.

public class Waiver
{
    public int WaiverID { get; set; }
    [Required(ErrorMessage = "Please select an Office")]
    [Range(1, int.MaxValue, ErrorMessage = "Please select an Office")]
    public int OfficeID { get; set; }

    public virtual Office Office { set;get;}
}

repository.Waivers need to change as below.

Updated

IEnumerable<Waiver> waiverList = repository.Waivers.Where(wl => waiverNum == 0 || wl.WaiverID == waiverNum).Where(wl => officeId == 0 || wl.OfficeID == officeId)

//...other search criteria

@model IEnumerable<Waiver>
<table>
@foreach (var item in Model)
{
    <tr>
        <td> @item.WaiverID </td>
        <td> @item.OfficeID </td>
        <td> @item.Office.Name </td>
    </tr>
}
</table>

Update

Change public IEnumerable<Waiver> Waivers => context.Waivers; to

public IEnumerable<Waiver> Waivers => context.Waivers.Include(o => o.Office);

If this did not work, you need to check your db context class and correctly set mappings between Waivers and Office tables inside model bindings.

Hope this helps.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download