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

如何在Razor Page的Create.cshtml中显示关联表数据

解决方案:动态替换Razor Page表单标签文本

问题背景

开发ASP.NET Core Razor Page的Supervisor创建页面时,需要将MemberComm1、MemberComm2字段的默认标签("Chair/Member Committee 1"等),替换为Committee表中对应CommitteeNo(固定为1、2)的CommitteeDesc值,无需将该标签值存入数据库。此前尝试使用集合类型时频繁遇到空对象错误,且在cshtml中使用return关键字导致语法报错。

步骤1:优化后台PageModel代码

修正CreateModel中的冗余代码和潜在问题,确保委员会数据在所有场景下都能正确加载:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Votes.Data;
using Votes.Model;

namespace Votes.Pages.Supervisors;

[BindProperties]
public class CreateModel : PageModel
{
    private readonly ApplicationDbContext _db;
    public Supervisor Supervisor { get; set; }
    public IEnumerable<Committee> DisplayCommitteeData { get; set; } 
    public IEnumerable<Municipality> DisplayMunicipalityData { get; set; }
    public IEnumerable<Ward> DisplayWardData { get; set; }
    public IEnumerable<District> DisplayDistrictData { get; set; }

    public CreateModel(ApplicationDbContext db)
    {
        _db = db;
        // 初始化集合避免空引用
        DisplayCommitteeData = Enumerable.Empty<Committee>();
        DisplayMunicipalityData = Enumerable.Empty<Municipality>();
        DisplayWardData = Enumerable.Empty<Ward>();
        DisplayDistrictData = Enumerable.Empty<District>();
    }

    public async Task OnGet()
    {
        // 直接加载所需数据,移除冗余查询
        DisplayCommitteeData = await _db.Committee.ToListAsync();
        DisplayMunicipalityData = await _db.Municipality.ToListAsync();
        DisplayWardData = await _db.Ward.ToListAsync();
        DisplayDistrictData = await _db.District.ToListAsync();
    }

    public async Task<IActionResult> OnPost()
    {
        if (ModelState.IsValid)
        {
            // 移除重复的Add操作
            await _db.Supervisor.AddAsync(Supervisor);
            await _db.SaveChangesAsync();
            TempData["success"] = "Supervisor added successfully.";
            return RedirectToPage("Index");
        }
        // 模型验证失败时,重新加载数据避免前端空引用
        DisplayCommitteeData = await _db.Committee.ToListAsync();
        DisplayMunicipalityData = await _db.Municipality.ToListAsync();
        DisplayWardData = await _db.Ward.ToListAsync();
        DisplayDistrictData = await _db.District.ToListAsync();
        return Page();
    }
}

关键优化点:

  • 构造函数中初始化集合为Enumerable.Empty<T>,避免未加载时的空引用
  • 移除OnGet中冗余的Select(...).ToListAsync()查询,直接加载完整数据集
  • OnPost验证失败时重新加载所有数据,确保返回Page()时前端能获取到有效数据
  • 移除重复的实体添加操作,避免数据异常

步骤2:前端cshtml动态渲染标签

在Create.cshtml中,手动渲染MemberComm1和MemberComm2的标签,从DisplayCommitteeData中动态获取对应CommitteeNo的CommitteeDesc:

<div class="form-group">
    @{
        // 获取CommitteeNo=1的委员会信息,为空时使用默认标签
        var committee1 = Model.DisplayCommitteeData.FirstOrDefault(c => c.CommitteeNo == 1);
        var comm1Label = committee1?.CommitteeDesc ?? "Chair/Member Committee 1";
    }
    <label class="control-label">@comm1Label</label>
    <select asp-for="Supervisor.MemberComm1" class="form-control">
        <option value="C">Chair</option>
        <option value="M">Member</option>
        <option value="X">Exclude</option>
    </select>
    <span asp-validation-for="Supervisor.MemberComm1" class="text-danger"></span>
</div>

<div class="form-group">
    @{
        // 获取CommitteeNo=2的委员会信息,为空时使用默认标签
        var committee2 = Model.DisplayCommitteeData.FirstOrDefault(c => c.CommitteeNo == 2);
        var comm2Label = committee2?.CommitteeDesc ?? "Chair/Member Committee 2";
    }
    <label class="control-label">@comm2Label</label>
    <select asp-for="Supervisor.MemberComm2" class="form-control">
        <option value="C">Chair</option>
        <option value="M">Member</option>
        <option value="X">Exclude</option>
    </select>
    <span asp-validation-for="Supervisor.MemberComm2" class="text-danger"></span>
</div>

关键说明:

  • 使用?.空条件运算符避免空引用异常
  • 用??空合并运算符设置默认标签,确保数据库中找不到对应委员会时仍有正常显示
  • 不再依赖asp-for自动生成标签,改为手动渲染实现动态替换

额外优化方案

如果需要统一管理标签逻辑,可在PageModel中添加计算属性,减少前端代码量:

public string Comm1Label => DisplayCommitteeData.FirstOrDefault(c => c.CommitteeNo == 1)?.CommitteeDesc ?? "Chair/Member Committee 1";
public string Comm2Label => DisplayCommitteeData.FirstOrDefault(c => c.CommitteeNo == 2)?.CommitteeDesc ?? "Chair/Member Committee 2";

前端直接使用:

<label class="control-label">@Model.Comm1Label</label>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:05:04