11

We send emails from our ASP.NET MVC 3 Razor Web Application.

Currently we're using ActionMailer.NET.

I've looked at MvcMailer.

The problem with both is that they need a Http Context to execute.

The problem with this is that i want to send emails asychronously. Now i know you can asynchronously do the actual send (e.g the SMTP call), but i want the entire process of sending an email to be asynchronous, e.g:

public ActionResult DoSomething(Something something)
{
   _db.Save(something);

   Task.Factory.StartNew(() => {
      new MailController().DoSomething().Send(something);
   });

   return RedirectToAction("Index");
}

In the "DoSomething" method, i query the database again, do other stuff, etc....i want all this to be asynchronous - hence the entire call is wrapped in a task, a opposed to just doing .SendAsync(). Hope that makes sense.

The above example is ActionMailer, and it breaks - because the HTTP context is gone in the spawned thread.

Does anyone know how i can get this to work, or alternatively another package which does not rely on the existence of a HTTP context?

I'm not sure why a HTTP context is required - there is no request routing here, simply parsing a view which is on the file system into HTML.

Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148
RPM1984
  • 72,246
  • 58
  • 225
  • 350
  • There's also the original RazorEngine https://github.com/Antaris/RazorEngine :) (initially developed by Antaris and myself but Antaris has taken it over completely) – Buildstarted May 30 '12 at 14:18

3 Answers3

1

You may checkout postal which uses the RazorViewEngine:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(5000);
            dynamic email = new Email("Example");
            email.To = "webninja@example.com";
            email.FunnyLink = "some funny link";
            email.Send();
        });

        return View();
    }
}

and inside ~/Views/Emails/Example.cshtml:

To: @ViewBag.To
From: lolcats@website.com
Subject: Important Message

Hello,
You wanted important web links right?
Check out this: @ViewBag.FunnyLink

Also make sure you have read and understood the dangers of implementing background tasks in ASP.NET applications before putting your application on production.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • what do you suggest then? A seperate email service would be great, but then it would actually need to be a seperate MVC web application, in order to make use of the razor view engine, and my domain/repository - would it not? I would then end up just doing HTTP calls to that "web site" in order to send the emails. How would you do it? – RPM1984 May 31 '12 at 08:12
  • You could use the RazorEngine package in your Windows Service which allows you to render Razor views outside of an ASP.NET MVC applications. – Darin Dimitrov May 31 '12 at 08:57
  • and what about if i need to access the routing table of the main site, in order to generate links to it? Will i have to somehow abstract the routing table into a common assembly? – RPM1984 Jun 01 '12 at 00:06
  • A colleague of mine had a thought, which is a tad dodgy, but it will work. I create a "secret" route inside my current application. In my controller where i would normally call ActionMailer, i do a "POST" to this secret url (i can pass secret headers to be safe) using async web client, then that URL maps a controller which sends the email. Basically "faking" a service inside the one application. Thoughts? – RPM1984 Jun 01 '12 at 00:39
1

ActionMailer.NET can now be used stand-alone outside of MVC.

The details are covered here

http://geeksharp.com/2011/07/06/actionmailer-0-6-released/

Eric J.
  • 147,927
  • 63
  • 340
  • 553
0

If you're using .NET 4.5 (or the Async CTP whatever it is) you may want to look into async ActionMethods. To be frank I'm not sure exactly what the requirements are (MVC 3/4) but that article should help.

I'm also not sure why you're that concerned about the time taken for the database lookup - is it really doing that much?

Better solution than SendAsync: I prefer to not to use SendAsync but to send through an SMTP server with the regular Send method, such as the one in IIS which is what I'm using (Note: you have to use the IIS6 console even if you're using IIS7 to administer your main IIS). This will then return instantly once your local machine has queued the email and you don't need to wait for it to be sent. Perhaps more importantly if there's an error sending it will keep retrying for you. Believe it or not - sometimes smtp.gmail.com doesn't respond.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689