MVCMailer SendAsync()因Amazon SES失败

时间:2013-02-26 20:29:59

标签: c# asp.net-mvc amazon-ses mvcmailer

如果我使用带有MVCMailer的Send(),我的SES工作正常,但SendAsync()显示下面的错误消息,是否有人知道解决此问题?谢谢!

System.Net.Mail.SmtpException: Failure sending mail. ---> System.InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>.
   at System.Web.AspNetSynchronizationContext.OperationStarted()
   at System.ComponentModel.AsyncOperation.CreateOperation(Object userSuppliedState, SynchronizationContext syncContext)
   at System.Net.Mail.SmtpClient.SendAsync(MailMessage message, Object userToken)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.SendAsync(MailMessage message, Object userToken)
   at Mvc.Mailer.SmtpClientWrapper.SendAsync(MailMessage mailMessage, Object userState)
   at Mvc.Mailer.MailMessageExtensions.SendAsync(MailMessage message, Object userState, ISmtpClient smtpClient)
   at MVCWebsite.Helpers.AccountHelper.RegisterNewUser(BaseDBContext db, AccountViewModelForReg VM, Boolean isCaptchaValid, Boolean modelValidity) in c:\Users\William-Business\Desktop\TWB\TWB Central\Projects\AwesomeSauce\AwesomeSauce\Helpers\AccountHelper.cs:line 316
   at MVCWebsite.Controllers.AccountController.Register(AccountViewModelForReg VM, Boolean captchaValid) in c:\Users\William-Business\Desktop\TWB\TWB Central\Projects\AwesomeSauce\AwesomeSauce\Controllers\AccountController.cs:line 308
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<>c__DisplayClass2a.<BeginInvokeAction>b__20()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult)

1 个答案:

答案 0 :(得分:5)

此错误是设计使然。你可以全局关闭它:

<appSettings>
  <add key="aspnet:AllowAsyncDuringSyncStages" value="false" />
</appSettings>

参考http://msdn.microsoft.com/en-us/library/hh975440.aspx

要考虑的其他事情是使用Task在后台执行异步,将其与ASP.Net使用的调度程序分离。使用此方法,您无需更改appSetting。

using Mvc.Mailer;
...
public ActionResult SendWelcomeMessage()
{
    Task.Factory.StartNew(() => UserMailer.Welcome().SendAsync());
    return RedirectToAction("Index");
}

修改

启用AllowAsyncDuringSyncStages或使用任务并行库都有潜在的缺点。使用AsyncController没有任何缺点。感谢@StephenCleary挑战我的答案。

public class HomeController : AsyncController
{
  public void SendMessageAsync()
  {
    var client = new SmtpClientWrapper();
    client.SendCompleted += (sender, args) => 
      AsyncManager.OutstandingOperations.Decrement();
    AsyncManager.OutstandingOperations.Increment();
    new UserMailer().Welcome().SendAsync("", client);
  }

  public ActionResult SendMessageCompleted()
  {
    return View();
  }
}