0

I have a problem about accessing third level navigation properties in my context. I have searched a lot for two days but could not find any issue close to mine. So I thought that I have a logical mistake about my approach.

I use the MVC template project. Model classes and context are below.

public partial class Tests
{

    [Key]
    public int TestID { get; set; }
    public string TestName { get; set; }
    public List<UserTests> UserTests { get; set; }
}

public partial class UserTests
{
    [Key, Column(Order=1)]
    public string UserID { get; set; }
    [Key, Column(Order = 2)]
    public int TestID { get; set; }
    public Nullable<double> TestValue { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    public Tests Tests { get; set; }
}

public partial class UserDetail
{

    [Key]
    public int ID { get; set; }
    public string UserID { get; set; }
    public string Name { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
}

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

    public List<UserTests> UserTests { get; set; }
    public List<UserDetail> UserDetails { get; set; }

}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
        this.Configuration.ProxyCreationEnabled = false;
        this.Configuration.LazyLoadingEnabled = false;
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    public IDbSet<Tests> Tests { get; set; }
    public IDbSet<UserDetail> UserDetails { get; set; }
    public IDbSet<UserTests> UserTests { get; set; }


}

I try to reach UserDetails properties from UserTests. But I can't find Select method inside the Include method clicking dot after ApplicationUser.

public ActionResult Index()
    {
        var userTests = db.UserTests.Include(u => u.Tests).Include(y => y.ApplicationUser.UserDetails);
        return View(userTest.ToList());
    }

This is the index view.

    @model IEnumerable<WebApplication6.Models.UserTests>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ApplicationUser.Email)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Tests.TestName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.TestValue)
        </th>

    </tr>

@foreach (var item in Model) {
    <tr>
        <th>
            @Html.DisplayFor(modelItem => item.ApplicationUser.Email)
        </th>
        <td>
            @Html.DisplayFor(modelItem => item.Tests.TestName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TestValue)
        </td>

        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}

</table>

I want the view to display ApplicationUser's Name instead of Email which is in the UserDetails model class. So I want to type a Razor code like below but I can't. There is no Name property after UserDetails

@Html.DisplayNameFor(model => model.ApplicationUser.UserDetails.Name)
  1. Why can't I find Select method there?
  2. Is there any way to access UserDetails properties from UserTests with include or another ef method?
  3. If not, how to send a model to the view that can be accessible to UserTests, ApplicationUser and UserDetails properties?
  4. How can I achieve to display UserDetails.Name property instead of ApplicationUser.Email property?
  • The `Select` method is an extension method defined to act on `IEnumerable`, `ApplicationUser` isn't a collection nor implements `IEnumerable` – chomba Apr 16 '15 at 21:47
  • @chomba, thank you for your comment. You are right. I have implemented IEnumerable to the ApplicationUser and then I could access to the `Select` method. But still I can't access the UserDetails' properties in the view. – Not Even a Junior Apr 17 '15 at 02:39

1 Answers1

0

This is the Include you're looking for:

db.UserTests.Include(x => x.ApplicationUser.UserDetails);
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
  • Thank you for your answer. I have tried that before but it didn't worked for me. When I send this to the view I can't access to the UserDetails.Name. – Not Even a Junior Apr 17 '15 at 02:48
  • `UserDetails.Name` doesn't exist. You should display names `foreach` UserDetail. – Gert Arnold Apr 17 '15 at 06:38
  • I can access to the UserDetail properties with nested `foreach` loops in `DisplayFor` area. But what to do in `DisplayNameFor` area? Should I write just string or send `UserDetails.Name` with ViewBag? Can I display the name there as strongly typed? – Not Even a Junior Apr 17 '15 at 13:34