我的asp.net mvc 5项目,并有一个页面,用户提交帖子并收到有关他们刚刚发布的帖子的电子邮件。我如何构建我的程序,以便用户看到一个网页确认邮件已经立即生成,然后服务器单独发送一封电子邮件?
这是我想出的: 使用2个控制器动作。当确认页面加载时,它通过javascript调用发送电子邮件操作?有更好的解决方案吗?
此外,电子邮件服务可能会失败,但这不应影响确认页面
更新:确认页面也应该在电子邮件发送或失败时通知用户
更新2: 它应该执行1然后立即返回。状态2并不重要 async的语法是什么?
public async Task<ActionResult> Confirm(string text)
{
//1. Save post to database
//2. Send email async
return View();
}
如果我不关心交货失败,这就是我需要的吗?
答案 0 :(得分:1)
您的标题具有误导性,因为发送电子邮件并不是一项非常耗时的任务,除非您希望发送大型附件或进行其他处理以创建电子邮件内容。根据我在大多数服务器上的经验,一封电子邮件会在几毫秒内发送。
对于您的示例,不需要添加两个控制器操作,也不需要asynch。
只需创建一个常规操作即可完成您的工作:
[HttpPost]
public ActionResult PostMessage(string messageText)
{
string result;
try
{
// mail.Send() here
// can use SendAsync but then need to handle result feedback via JavaScript
result = "Email was sent";
}
catch
{
result = "Sending Email Failed";
}
return View("PostConfirmation", result);
}
编辑: 如果您的网络不可靠,我会发送异步电子邮件并在确认屏幕上显示“电子邮件排队”。
如果您想远离JavaScript轮询,那么只需在行动开始时通过以下内容存储来自后台任务的消息:ViewBag.AsynchMessage =“您的帖子是通过电子邮件发送的”结果。只需在主布局中将ViewBag包含在合适的位置,您的用户就可以在处理时看到消息。不要忘记在后续请求中清空ViewBag以保持UI清洁。
答案 1 :(得分:1)
您可以使用SmtpClient.SendAsync()以异步方式直接从控制器发送邮件,前提是您依赖System.Net.Mail
作为提供商,而不是外部扩展。
控制器中的语法示例:
[HttpPost]
public ActionResult PostData(object data)
{
//1. Save your post data here...
MailMessage myMessage = new MailMessage();
//2. Play with your message object here...
SmtpClient myClient = new SmtpClient("your.smtp.com", 587);
myClient.SendAsync(myMessage, "myToken");
return View();
}
如果您稍后关注这些内容,则必须使用Javascript处理视图中的返回值。
我不得不同意@HighCs的意思 - 确认电子邮件,即使是带有少量数据的HTML消息,也不需要花费很长时间才能发送您需要担心异步操作。您可以通过执行以下操作来包括您确认邮件发送的原始请求:
[HttpPost]
public ActionResult PostData(object data)
{
//...Save your post data here...
MailMessage myMessage = new MailMessage();
//...Play with your message object here...
SmtpClient myClient = new SmtpClient("your.smtp.com", 587);
bool sentOk = true;
try
{
myClient.Send(myMessage);
}
catch
{
sentOk = false;
}
return RedirectToAction("PostConfirmed", new { confirmEmail = sentOk });
}
你可以做任何你想要生成&#34; PostConfirmed&#34;查看,您可以使用confirmEmail
布尔值来调整视图的内容,具体取决于电子邮件错误。
还有关于async
请求here的一些更深入的信息。
编辑:根据您对@HighCs关于连接失败的评论,请考虑在SmtpClient
配置中实施此操作:SmtpClient.Timeout()
答案 2 :(得分:0)
如果您不想等待数据库保存和邮件发送,您可以创建任务并立即返回:
public ActionResult PostData(string text)
{
//1. Save post to database
var databaseTask = Task.Factory.StartNew(this.SavePostToDatabase);
//2. Send email async
databaseTask.ContinueWith(task => this.SendEmail());
//3. Confirmation view
return RedirectToAction("PostConfirmed");
}
protected void SendEmail()
{
throw new NotImplementedException();
}
private void SavePostToDatabase()
{
throw new NotImplementedException();
}