ASP.NET MVC模型依赖实现:为Loan添加公司选择下拉列表
ASP.NET MVC 借贷记录表单实现方案
1. 修正模型关联定义
首先明确Company与Loan的一对多关联规则,通过EF实现正确的外键和导航属性:
// Company模型 public class Company { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } // 导航属性:该公司作为出借方的所有借贷记录 public ICollection<Loan> GivenLoans { get; set; } = new List<Loan>(); // 导航属性:该公司作为借入方的所有借贷记录 public ICollection<Loan> ReceivedLoans { get; set; } = new List<Loan>(); } // Loan模型 public class Loan { public int Id { get; set; } public decimal Amount { get; set; } public DateTime LoanDate { get; set; } // 出借方外键 public int FromCompanyId { get; set; } public Company FromCompany { get; set; } // 借入方外键 public int ToCompanyId { get; set; } public Company ToCompany { get; set; } }
在DbContext中用Fluent API明确关联规则(可选,增强可读性):
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Loan>() .HasOne(l => l.FromCompany) .WithMany(c => c.GivenLoans) .HasForeignKey(l => l.FromCompanyId) .OnDelete(DeleteBehavior.Restrict); // 防止删除公司时连带删除借贷记录 modelBuilder.Entity<Loan>() .HasOne(l => l.ToCompany) .WithMany(c => c.ReceivedLoans) .HasForeignKey(l => l.ToCompanyId) .OnDelete(DeleteBehavior.Restrict); }
2. 创建视图模型(ViewModel)
为了同时传递借贷表单数据和公司下拉选项,定义专用视图模型:
public class CreateLoanViewModel { [Required(ErrorMessage = "请输入借贷金额")] public decimal Amount { get; set; } [Required(ErrorMessage = "请选择借贷日期")] public DateTime LoanDate { get; set; } [Required(ErrorMessage = "请选择出借公司")] public int FromCompanyId { get; set; } [Required(ErrorMessage = "请选择借入公司")] public int ToCompanyId { get; set; } // 公司下拉选项集合 public IEnumerable<SelectListItem> CompanyOptions { get; set; } }
3. 完善控制器逻辑
在LoansController中实现GET和POST方法,处理数据加载和表单提交:
GET方法(加载表单)
private readonly ApplicationDbContext _context; public LoansController(ApplicationDbContext context) { _context = context; } public IActionResult Create() { // 查询所有公司,转换为下拉选项 var companyOptions = _context.Companies .Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.Name }) .ToList(); var viewModel = new CreateLoanViewModel { CompanyOptions = companyOptions, LoanDate = DateTime.Now // 默认填充当前日期 }; return View(viewModel); }
POST方法(提交表单)
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(CreateLoanViewModel viewModel) { if (!ModelState.IsValid) { // 验证失败时重新加载公司选项 viewModel.CompanyOptions = _context.Companies .Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.Name }) .ToList(); return View(viewModel); } // 将视图模型转换为Loan实体 var loan = new Loan { Amount = viewModel.Amount, LoanDate = viewModel.LoanDate, FromCompanyId = viewModel.FromCompanyId, ToCompanyId = viewModel.ToCompanyId }; _context.Loans.Add(loan); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); }
4. 实现视图下拉列表
在Create.cshtml中生成下拉选择框,并添加表单验证:
@model CreateLoanViewModel @{ ViewData["Title"] = "新建借贷记录"; } <h1>新建借贷记录</h1> <div class="row"> <div class="col-md-4"> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Amount" class="control-label"></label> <input asp-for="Amount" class="form-control" /> <span asp-validation-for="Amount" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="LoanDate" class="control-label"></label> <input asp-for="LoanDate" type="date" class="form-control" /> <span asp-validation-for="LoanDate" class="text-danger"></span> </div> <div class="form-group"> <label class="control-label">出借公司</label> @Html.DropDownListFor(m => m.FromCompanyId, Model.CompanyOptions, "请选择公司", new { @class = "form-control" }) <span asp-validation-for="FromCompanyId" class="text-danger"></span> </div> <div class="form-group"> <label class="control-label">借入公司</label> @Html.DropDownListFor(m => m.ToCompanyId, Model.CompanyOptions, "请选择公司", new { @class = "form-control" }) <span asp-validation-for="ToCompanyId" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="创建" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">返回列表</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <script> // 禁止选择同一公司作为出借和借入方 document.getElementById('FromCompanyId').addEventListener('change', function() { const toSelect = document.getElementById('ToCompanyId'); const selectedFrom = this.value; for (let i = 0; i < toSelect.options.length; i++) { toSelect.options[i].disabled = toSelect.options[i].value === selectedFrom; } }); </script> }
5. 额外优化建议
- 若公司数据量大,可添加搜索功能或分页加载下拉选项
- 可在服务器端添加验证,禁止出借方和借入方为同一公司
- 可通过EF迁移确保数据库表结构正确生成
内容的提问来源于stack exchange,提问作者Thibault_Km
相关产品推荐
相关产品推荐

