如何在同一ASP.NET MVC视图中显示表单及提交后的单用户详情?
实现方案说明
核心思路
要在同一视图同时展示表单和当前用户的教育记录,需要组合ViewModel来同时承载表单数据和用户记录列表,然后在Index的HttpGet和HttpPost方法中分别处理初始化和提交后的记录刷新逻辑。
步骤1:创建组合ViewModel
新建一个ViewModel,同时包含表单模型和用户记录列表:
public class HiringEduViewModel { // 表单绑定用的模型 public VMHiring_edu_Info FormModel { get; set; } // 当前用户的教育记录列表 public List<Hiring_Edu_Info> UserEduRecords { get; set; } }
步骤2:修改HttpGet Index方法
在HiringController的HttpGet Index中,初始化组合ViewModel,并通过Linq查询当前用户的所有教育记录:
public ActionResult Index() { // 获取当前用户ID(如果用ASP.NET Identity,用下面的代码;自定义用户体系请替换成你的获取方式) var userId = User.Identity.GetUserId(); var viewModel = new HiringEduViewModel { FormModel = new VMHiring_edu_Info(), // Linq过滤当前用户的记录 UserEduRecords = db.Hiring_Edu_Info.Where(e => e.UserId == userId).ToList() }; return View(viewModel); }
步骤3:修改HttpPost Index方法
处理表单提交逻辑,插入数据后重定向到HttpGet Index(避免刷新重复提交),同时修正原代码的问题(比如缺失文件保存、拼写错误):
[HttpPost] public ActionResult Index(HiringEduViewModel viewModel) { if (ModelState.IsValid) { var tbEdu = viewModel.FormModel; var fileNameWithoutExt = Path.GetFileNameWithoutExtension(tbEdu.Attachment.FileName); var ext = Path.GetExtension(tbEdu.Attachment.FileName); var fullFileName = fileNameWithoutExt + ext; var savePath = Path.Combine(Server.MapPath("~/Images/"), fullFileName); var uploadedFile = tbEdu.Attachment; var fileSize = uploadedFile.ContentLength; bool insertSuccess = false; // 简化文件格式判断 var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".pdf" }; if (allowedExtensions.Contains(ext.ToLower()) && fileSize <= 400000) { var newEduRecord = new Hiring_Edu_Info { Level = tbEdu.Level, Board_Uni_Ins = tbEdu.Board_Uni_Ins, City = tbEdu.City, Country = tbEdu.Country, Year_Passing = tbEdu.Year_Passing, Division = tbEdu.Division, Grade = tbEdu.Grade, CGPA = tbEdu.CGPA, Percentage = tbEdu.Percentage, M_Obtained = tbEdu.M_Obtained, M_Total = tbEdu.M_Total, Attachment = savePath, IsDegreeCompleted = tbEdu.IsDegreeCompleted == "1", // 直接从当前用户获取ID,避免前端传参风险 UserId = User.Identity.GetUserId(), Degree_Title = tbEdu.Degree_Title }; db.Hiring_Edu_Info.Add(newEduRecord); var affectedRows = db.SaveChanges(); if (affectedRows > 0) { // 必须保存上传的文件到服务器 uploadedFile.SaveAs(savePath); // 用TempData传递提示信息(跨请求有效) TempData["Message"] = "<script>alert('记录插入成功')</script>"; // 重定向到Get方法,刷新页面和记录 return RedirectToAction("Index"); } } TempData["Message"] = "<script>alert('记录插入失败,请检查文件格式和大小')</script>"; } // 验证失败或插入失败时,重新获取用户记录返回视图 var userId = User.Identity.GetUserId(); viewModel.UserEduRecords = db.Hiring_Edu_Info.Where(e => e.UserId == userId).ToList(); return View(viewModel); }
步骤4:修改视图代码
将视图的模型换成组合ViewModel,在表单下方添加表格展示用户记录:
@model Edu_Form.Models.HiringEduViewModel @{ ViewBag.Title = "Index"; } <h2>教育信息录入</h2> <!-- 显示提示信息 --> @if (TempData["Message"] != null) { @Html.Raw(TempData["Message"]) } @using (Html.BeginForm("Index", "Hiring", FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>教育信息表单</h4> <hr /> <div class="row"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <!-- 注意所有表单字段要绑定到Model.FormModel --> <div class="form-group"> @Html.LabelFor(model => model.FormModel.Year_Passing, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.FormModel.Year_Passing, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.FormModel.Year_Passing, "", new { @class = "text-danger" }) </div> </div> <!-- 其他表单字段同样修改为Model.FormModel.XXX --> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="提交" class="btn btn-default" /> </div> </div> </div> </div> } <!-- 表单下方显示用户教育记录表格 --> <h3>我的教育记录</h3> @if (Model.UserEduRecords.Any()) { <table class="table table-striped table-bordered"> <thead> <tr> <th>学位名称</th> <th>毕业年份</th> <th>成绩等级</th> <th>附件</th> <!-- 按需添加其他字段 --> </tr> </thead> <tbody> @foreach (var record in Model.UserEduRecords) { <tr> <td>@record.Degree_Title</td> <td>@record.Year_Passing</td> <td>@record.Grade</td> <td> @if (!string.IsNullOrEmpty(record.Attachment)) { // 转换服务器路径为相对路径,用于前端访问 var relativePath = record.Attachment.Replace(Server.MapPath("~/"), "~/"); <a href="@Url.Content(relativePath)" target="_blank">查看附件</a> } </td> </tr> } </tbody> </table> } else { <p>暂无教育记录,请添加。</p> }
关键说明
代码编写位置:
- 记录查询逻辑写在
HttpGet Index,用于页面初始化时加载用户已有记录 - 表单提交和插入逻辑写在
HttpPost Index,完成后重定向到Get方法刷新记录
- 记录查询逻辑写在
注意事项:
- 原代码缺失上传文件的保存步骤,必须添加
uploadedFile.SaveAs(savePath),否则数据库路径无效 - 用
TempData代替ViewBag传递提示信息,因为重定向后ViewBag会失效 - Linq查询通过
Where(e => e.UserId == userId)过滤当前用户的记录,确保只显示该用户的信息
- 原代码缺失上传文件的保存步骤,必须添加
内容的提问来源于stack exchange,提问作者Shaheer Ahmed
相关产品推荐
相关产品推荐

