.NET Core批量打印学生证问题:如何在foreach循环返回全部数据
解决.NET Core学生证批量打印仅显示最后一名学生的问题
我来帮你搞定这个批量打印的问题——你现在的代码之所以只返回最后一名学生的数据,是因为在控制器的循环里,每次都覆盖了ViewBag的单个属性(比如FullName、QRCodeImage)和模型的Student对象,最后只有循环最后一次的学生数据被保留下来。要实现批量返回选中学生的全部数据,我们需要调整数据传递的方式,把所有学生的信息封装成列表传给视图,而不是反复覆盖单个值。
1. 创建批量学生证视图模型
首先定义一个专门的视图模型,用来存储每个学生打印学生证需要的所有数据,避免依赖零散的ViewBag属性:
public class StudentCardViewModel { public string FullName { get; set; } public string MatricNumber { get; set; } public Department Department { get; set; } public Faculty Faculty { get; set; } public string PassportUrl { get; set; } public string SignatureUrl { get; set; } public string QRCodeImageBase64 { get; set; } public string Gender { get; set; } public string SessionName { get; set; } public string ClassLevel { get; set; } // 按需添加其他你需要的字段 }
2. 修改控制器的BulkCard方法
调整控制器逻辑,批量查询学生数据,生成每个学生的完整信息列表,再传递给视图:
[HttpGet] [AllowAnonymous] public IActionResult BulkCard() { // 获取选中的学生ID列表 var selectedStudentIds = TempData["students"] as object[]; if (selectedStudentIds == null || !selectedStudentIds.Any()) { // 没有选中学生的处理逻辑,比如跳回学生选择页面 return RedirectToAction("StudentList"); } // 批量查询所有选中的学生(一次性查询,优化EF性能) var studentIds = selectedStudentIds.Select(id => Convert.ToInt32(id)).ToList(); var students = _context.Students .Include(c => c.Department) .Include(c => c.Department.Faculty) .Include(c => c.ProgramType) .Include(c => c.ClassLevels) .Include(c => c.Session) .Where(c => studentIds.Contains(c.Id)) .ToList(); // 生成每个学生的学生证视图模型列表 var studentCardViewModels = new List<StudentCardViewModel>(); foreach (var student in students) { // 组装全名 var fullname = $"{student.Surname} {student.FirstName} {student.MiddleName[0]}."; // 生成二维码并转为Base64 string qrCodeBase64 = null; var qrdata = student.QRCodeData.ToString().Replace("/", ""); using (MemoryStream ms = new MemoryStream()) { QRCodeGenerator qrGenerator = new QRCodeGenerator(); QRCodeData qrCodeData = qrGenerator.CreateQrCode(qrdata, QRCodeGenerator.ECCLevel.Q); QRCode qrCode = new QRCode(qrCodeData); using (Bitmap bitMap = qrCode.GetGraphic(20)) { bitMap.Save(ms, ImageFormat.Png); qrCodeBase64 = "data:image/png;base64," + Convert.ToBase64String(ms.ToArray()); } } // 添加到视图模型列表 studentCardViewModels.Add(new StudentCardViewModel { FullName = fullname, MatricNumber = student.MatricNumber, Department = student.Department, Faculty = student.Department.Faculty, PassportUrl = $"/Uploads/Passport/{student.Passport}", SignatureUrl = $"/Uploads/Signature/{student.Signature}", QRCodeImageBase64 = qrCodeBase64, Gender = student.Gender, SessionName = student.Session.SessionName, ClassLevel = student.ClassLevels.ClassLevel }); } // 设置模板信息 var designtemplate = _context.Settings.First(); switch (designtemplate.CardTemplate) { case 1: ViewBag.Template = "1"; break; case 2: ViewBag.Template = "2"; ViewBag.TemplateView = "This is template 2"; break; case 3: ViewBag.Template = "3"; ViewBag.TemplateView = "This is template 3"; break; default: return RedirectToAction("CardSettings", "Settings"); } // 把视图模型列表传给视图 return View(studentCardViewModels); }
3. 修改视图代码
将视图改为强类型绑定到视图模型列表,循环遍历每个学生的信息进行渲染:
@model List<StudentCardViewModel> @foreach (var card in Model) { @if (ViewBag.Template == "1") { <!-- 模板1的完整学生证结构,替换所有ViewBag属性为card对应的属性 --> <table> <tr> <td> <div class="wrapper"> <div class="container"> <div style="position: absolute;color: lightgray;opacity: 0.05;font-size: 3em;width: 50%;top: 25%; left: 80px;text-align: center;z-index: 0;background-attachment: fixed;"> <img src="~/img/fedpolel-Logo.png" width="150" /> </div> <img src="@card.PassportUrl" alt="" class="profile-img"> <img src="~/img/fedpolel-Logo.png" class="logo" /> <img src="@card.QRCodeImageBase64" class="qrcode"> <div class="content"> <table> <tr> <td> <div class="title"> <h4>THE FEDERAL POLYTECHNIC</h4> <span>ILE OLUJI, ONDO STATE.</span> </div> <div class="sub-content"> <center> <h1>@card.FullName</h1> </center> <p>@card.MatricNumber</p> </div> <div class="vr"></div> <div class="vr-right"></div> <div class="data"> <div class="inner-data"> <span>Gender</span> <p>@card.Gender<p /> <br> <span>Session</span> <p class="session">@card.SessionName</p> </div> <div class="inner-data2"> <span>Level</span> <p>@card.ClassLevel</p> <span>Department</span> <p>@card.Department.DepartmentName</p> <span>Faculty</span> <p>@card.Faculty.FacultyName</p> </div> <div class="inner-data3"> <div class="hr"></div> <p><img src="@card.SignatureUrl" width="50" /></p> <div class="paragra">Signature</div> </div> </div> </td> </tr> </table> </div> </div> </div> </td> </tr> </table> } else if (ViewBag.Template == "2") { @ViewBag.TemplateView <!-- 可在此添加模板2的具体渲染逻辑,使用card的属性 --> } else if (ViewBag.Template == "3") { @ViewBag.TemplateView <!-- 可在此添加模板3的具体渲染逻辑,使用card的属性 --> } else { <p>No valid template selected</p> } }
关键修复点说明
- 避免覆盖单个值:原来的循环中每次给
ViewBag.FullName、ViewBag.QRCodeImage赋值,会覆盖之前的值,最后只有最后一个学生的数据保留。现在我们把每个学生的所有数据存入列表,视图遍历列表即可获取每个学生的信息。 - EF性能优化:原来的循环中每次查询所有学生再
FirstOrDefault,现在改为一次性用Where(c => studentIds.Contains(c.Id))查询所有选中的学生,减少数据库查询次数。 - 强类型视图:使用强类型视图模型替代零散的ViewBag,代码更易维护,也避免了ViewBag的类型转换问题。
内容的提问来源于stack exchange,提问作者Daniel Omilegan
相关产品推荐
相关产品推荐

