2

I have contact form that logs a serialized version of a contact model to a database and sends an email with the form data. Between the two actions, it takes up to 2 seconds to complete. Although not a lot of time, it is enough to annoy impatient users.

Contact Controller:

public class ContactController : Controller
    {
        // GET: Contact
        public ActionResult Index()
        {
            return View();
        }

        // Post: /Contact/
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index(Models.ContactModel contact)
        {
            if (ModelState.IsValid)
            {

                XmlSerializer xmlSerializer = new XmlSerializer(contact.GetType());
                using (StringWriter textWriter = new StringWriter())
                {
                    xmlSerializer.Serialize(textWriter, contact);
                    Log.Create("email", textWriter.ToString());
                }

                Smtp.sendMail(sendTo, contact.Email, contact.Name, subject, contact.Comment,
                              ipAddress, senderEmail, contact.Phone, sendBcc);

                // using RedirectToRoute instead of RedirectToAction so that /contact is used.
                return RedirectToRoute("Default", new { action = "contactsucess", controller = "contact" });
            }

            // Return Form if not valid
            return View(contact);
        }

        // GET: /Contact/ContactSucess
        public ActionResult ContactSucess()
        {
            ViewBag.IsContactPage = true;

            return View();
        }
    }

What is the best approach to make serializing, logging and STMP logic asynchronous to the controller returning the success/thank you page. Basically my goal is to prevent those calls from blocking the overall progress so that the form completes faster.

Josh
  • 8,219
  • 13
  • 76
  • 123

1 Answers1

4

The common solution in my working experience is to move the emailer to another process.

The web server communicates to the emailer via messaging bus such as MSMQ, NServiceBus or RabbitMQ. When the web server wants to send an email, it sends a message to the emailer which does the actual email sending.

LostInComputer
  • 15,188
  • 4
  • 41
  • 49
  • Yes - And if you can run on Azure, look at Azure Web Jobs as a way to implement these out of process batch operations. Adding a link to Hanselman's blog http://www.hanselman.com/blog/IntroducingWindowsAzureWebJobs.aspx – Yishai Galatzer Jul 27 '14 at 17:37
  • I was thinking of a queue, but it seemed like overkill for sending an email. – Josh Jul 27 '14 at 20:53
  • It is not an overkill, it is the way it should be done. You can probably use MSMQ and a Windows service in the same machine than your web server. – vtortola Jul 28 '14 at 09:09
  • I'm using an Azure Web Site, so I'm going to try to implement using a Queue and an Azure WebJob. – Josh Jul 29 '14 at 23:26