You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过外键在Index页面引用关联模型的字段值

问题描述

我在Officer模型中通过外键关联了警员所属的Agency模型,支持用户在警员创建页面为警员分配机构。但在Officers列表页面(Index)中,希望显示该外键对应的Agency模型的AgencyName文本值(可同时显示外键ID),而非仅显示外键ID,以提升用户体验。

模型代码

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace DWITracker.Model
{
    public class Officer
    {
        [Key]
        public int Id { get; set; }
        [Display(Name ="Officer Name (Last, First, MI)")]
        public string? OfficerDisplayName { get; set; }
        [Display(Name = "First Name")]
        public string? OfficerFirstName { get; set; }
        [Display(Name = "MI")]
        public string? OfficerMiddleInitial { get; set; }
        [Display(Name = "Last Name")]
        public string? OfficerLastName { get; set; }
        [ForeignKey("Agency")]
        public int AgencyId { get; set; }
        [Display(Name = "Agency ID")]
        public Agency? Agency { get; set; }
    }
}

using System.ComponentModel.DataAnnotations;

namespace DWITracker.Model
{
    public class Agency
    {
        [Key]
        public int Id { get; set; }
        [Required]
        [Display(Name = "Agency")]
        public string AgencyName { get; set; }
    }
}

Index页面视图代码(显示AgencyName的部分)

<tbody>
    @foreach(var obj in Model?.Officer)
    {
    <tr>
        <td width="30%">@obj.OfficerDisplayName</td>
        <td width="10%">@obj.AgencyId</td>
        <td width="30%">@obj.Agency?.AgencyName</td>
        <td width="15%">@obj.UpdatedBy</td>
        <td width="15%">@obj.UpdateDate.ToShortDateString()</td>
        <td width="10%">
            <div class="w-75 btn-group" role="group">
                <a asp-page="Edit" asp-route-id="@obj.Id" class="btn btn-primary mx-2">
                    <i class="bi bi-pencil-square"></i>
                </a>
                <a asp-page="Delete" asp-route-id="@obj.Id" class="btn btn-danger mx-2">
                    <i class="bi bi-trash-fill"></i>
                </a>
            </div>
        </td>
    </tr>
    }
</tbody>

Index.cshtml.cs代码

using DWITracker.Data;
using DWITracker.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Reflection;

namespace DWITracker.Pages.Officers;

public class IndexModel : PageModel
{
    public IEnumerable<Officer> Officer { get; set; }

    private readonly ILogger<IndexModel> _logger;
    private readonly ApplicationDbContext _db;

    [BindProperty]
    public List<Officer>? OfficersList { get; set; }

    public IndexModel(ILogger<IndexModel> logger, ApplicationDbContext db)
    {
        _logger = logger;
        _db = db;
    }

    public string OfficerSort { get; set; }
    public string CurrentFilter { get; set; }

    public async Task OnGetAsync(string sortOrder, string searchString, List<Officer>OfficersList)
    {

        this.OfficersList = await _db.Officer.Include(x => x.Agency).AsNoTracking().ToListAsync();

        OfficerSort = sortOrder == "Officer_Asc_Sort" ? "Officer_Desc_Sort" : "Officer_Asc_Sort";
        CurrentFilter = searchString;

        IQueryable<Model.Officer> findOfficer = from s in _db.Officer select s;

        if (!String.IsNullOrEmpty(searchString))
           findOfficer = findOfficer.Where(s => s.OfficerDisplayName.Contains(searchString));

        switch (sortOrder)
        {
            case "Officer_Asc_Sort":
                findOfficer = findOfficer.OrderBy(s => s.OfficerDisplayName);
                break;
            case "Officer_Desc_Sort":
                findOfficer = findOfficer.OrderByDescending(s => s.OfficerDisplayName);
                break;
            default:
                findOfficer = findOfficer.OrderBy(s => s.OfficerDisplayName);
                break;
        }
        OfficersList = await findOfficer.AsNoTracking().ToListAsync();
    }
}

解决方案

1. 修正后台查询逻辑,确保加载Agency导航属性

当前后台代码中,虽然一开始通过Include(x => x.Agency)加载了关联数据,但后续重新查询时未包含该关联,导致Agency导航属性为空。同时方法参数中的List<Officer> OfficersList属于冗余参数,需移除。

修改后的OnGetAsync方法:

public async Task OnGetAsync(string sortOrder, string searchString)
{
    OfficerSort = sortOrder == "Officer_Asc_Sort" ? "Officer_Desc_Sort" : "Officer_Asc_Sort";
    CurrentFilter = searchString;

    // 初始化查询时就包含Agency关联
    IQueryable<Model.Officer> findOfficer = _db.Officer.Include(x => x.Agency);

    if (!String.IsNullOrEmpty(searchString))
        findOfficer = findOfficer.Where(s => s.OfficerDisplayName.Contains(searchString));

    switch (sortOrder)
    {
        case "Officer_Asc_Sort":
            findOfficer = findOfficer.OrderBy(s => s.OfficerDisplayName);
            break;
        case "Officer_Desc_Sort":
            findOfficer = findOfficer.OrderByDescending(s => s.OfficerDisplayName);
            break;
        default:
            findOfficer = findOfficer.OrderBy(s => s.OfficerDisplayName);
            break;
    }
    OfficersList = await findOfficer.AsNoTracking().ToListAsync();
}

2. 修正视图中的循环数据源

视图中当前循环的是Model?.Officer,但后台赋值的是OfficersList,需统一:

@foreach(var obj in Model?.OfficersList)

3. 优化Agency信息显示(可选)

若需同时显示AgencyID和名称,可修改对应单元格的内容:

<td width="30%">@obj.AgencyId - @obj.Agency?.AgencyName</td>

或保留原有分开显示的方式,确保@obj.Agency?.AgencyName能正常取值。


内容的提问来源于stack exchange,提问作者MelB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 13:21:28