网站上耗时的任务

时间:2014-07-24 00:42:17

标签: c# .net asp.net-mvc

我的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();
}

如果我不关心交货失败,这就是我需要的吗?

3 个答案:

答案 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();
}