ASP.Net MVC EF6实现点击按钮批量调用控制器方法给学生发邮件
没问题,我帮你一步步实现这个批量发邮件的功能,分几个核心环节来拆解,保证清晰易懂:
1. 先定义一个视图模型(ViewModel)
因为你需要收集发件人信息,同时关联学生列表,所以先创建一个专门的ViewModel来封装这些数据,方便在视图和控制器之间传递:
public class SendEmailViewModel { [Required(ErrorMessage = "请输入你的姓名")] public string SenderName { get; set; } [Required(ErrorMessage = "请输入你的邮箱")] [EmailAddress(ErrorMessage = "邮箱格式不正确")] public string SenderEmail { get; set; } [Required(ErrorMessage = "请输入消息内容")] public string MessageContent { get; set; } // 存储待发送的学生列表(从EF查询得到) public List<mytable> Students { get; set; } }
2. 改造原有的Project控制器方法
把原来的Project方法改成返回ViewModel,这样视图能拿到学生列表和发件人表单的绑定数据:
public ActionResult Project(int? id) { // 替换成你的EF查询逻辑,根据id获取对应的学生列表 var students = db.mytable.Where(s => s.ProjectId == id).ToList(); var viewModel = new SendEmailViewModel { Students = students // 可选:如果需要默认填充发件人信息,在这里赋值 }; return View(viewModel); }
3. 设计视图页面(Project.cshtml)
视图需要包含发件人信息表单、学生列表预览,以及提交按钮。注意用POST方式提交表单,确保数据安全:
@model YourNamespace.SendEmailViewModel @{ ViewBag.Title = "批量发送学生邮件"; } <!-- 显示发送结果提示 --> @if (TempData["SendResult"] != null) { <div class="alert alert-info">@TempData["SendResult"]</div> } <h2>给学生发送消息</h2> @using (Html.BeginForm("SendBulkEmails", "YourControllerName", FormMethod.Post, new { @class = "form-horizontal" })) { @Html.AntiForgeryToken() <!-- 发件人姓名 --> <div class="form-group"> @Html.LabelFor(m => m.SenderName, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.TextBoxFor(m => m.SenderName, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.SenderName, "", new { @class = "text-danger" }) </div> </div> <!-- 发件人邮箱 --> <div class="form-group"> @Html.LabelFor(m => m.SenderEmail, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.TextBoxFor(m => m.SenderEmail, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.SenderEmail, "", new { @class = "text-danger" }) </div> </div> <!-- 消息内容 --> <div class="form-group"> @Html.LabelFor(m => m.MessageContent, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.TextAreaFor(m => m.MessageContent, new { @class = "form-control", rows = 6 }) @Html.ValidationMessageFor(m => m.MessageContent, "", new { @class = "text-danger" }) </div> </div> <!-- 隐藏传递Project的id,用于控制器重新查询学生列表(避免前端篡改) --> @Html.Hidden("id", ViewContext.RouteData.Values["id"]) <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <button type="submit" class="btn btn-primary">发送邮件</button> </div> </div> } <!-- 预览待发送的学生列表 --> <h3>待发送学生清单</h3> <table class="table table-striped"> <thead> <tr> <th>学生姓名</th> <th>邮箱地址</th> </tr> </thead> <tbody> @foreach (var student in Model.Students) { <tr> <td>@student.Name</td> <td>@student.Email</td> </tr> } </tbody> </table>
4. 实现批量发送的控制器方法,循环调用Contact
首先假设你已经有了单封邮件发送的Contact方法,我们基于它扩展批量发送逻辑:
先完善单封邮件的Contact方法(异步版本更友好)
// 异步发送单封邮件的方法 private async Task<bool> SendSingleEmail(string senderName, string senderEmail, string studentEmail, string message) { try { var mail = new System.Net.Mail.MailMessage(); mail.From = new System.Net.Mail.MailAddress(senderEmail, senderName); mail.To.Add(studentEmail); mail.Subject = $"来自{senderName}的通知"; mail.Body = message; mail.IsBodyHtml = false; // 若需要HTML内容,改为true // 替换成你的SMTP配置(比如QQ/163邮箱的SMTP服务器) using (var smtp = new System.Net.Mail.SmtpClient("smtp.qq.com", 587)) { smtp.Credentials = new System.Net.NetworkCredential("你的邮箱账号", "SMTP授权码"); smtp.EnableSsl = true; await smtp.SendMailAsync(mail); } return true; } catch (Exception ex) { // 这里建议记录日志,比如用Log4net/NLog记录发送失败的异常 // Log.Error($"给{studentEmail}发送邮件失败:{ex.Message}"); return false; } }
添加批量发送的Action方法
[HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> SendBulkEmails(SendEmailViewModel model, int? id) { // 先验证表单数据是否合法 if (!ModelState.IsValid) { model.Students = db.mytable.Where(s => s.ProjectId == id).ToList(); return View("Project", model); } // 重新从数据库查询学生列表(安全起见,不依赖前端传递的数据) var students = db.mytable.Where(s => s.ProjectId == id).ToList(); int successCount = 0; int failCount = 0; // 循环给每个学生发送邮件 foreach (var student in students) { var isSuccess = await SendSingleEmail(model.SenderName, model.SenderEmail, student.Email, model.MessageContent); if (isSuccess) successCount++; else failCount++; } // 把发送结果通过TempData传递到视图 TempData["SendResult"] = $"邮件发送完成:成功{successCount}封,失败{failCount}封"; return RedirectToAction("Project", new { id = id }); }
几个关键注意事项
- SMTP配置:不同邮箱的SMTP服务器和端口不一样,比如QQ邮箱是
smtp.qq.com:587,需要开启POP3/SMTP服务并生成授权码(不要用登录密码)。 - 异步处理:用
async/await避免长时间阻塞请求,提升用户体验,尤其是学生数量较多时。 - 安全问题:控制器里重新查询学生列表,而不是依赖前端传递的邮箱,防止恶意篡改收件人。
- 性能优化:如果学生数量极大,可以考虑用
Parallel.ForEach并行发送,但要注意SMTP服务器的并发限制,避免被封禁。
内容的提问来源于stack exchange,提问作者Rawan
相关产品推荐
相关产品推荐

