MVCMailer SendAsync() fails with Amazon SES

六月ゝ 毕业季﹏ 提交于 2019-12-04 04:27:35

问题


If I use Send() with MVCMailer, my SES works fine, but SendAsync() shows the error message below, does anyone know of a work around for this? THanks!

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:


This error is by design. You can turn this off globally:

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

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

Something else to consider is using a Task to do the async in the background, decoupling it from the scheduler that ASP.Net uses. Using this method, you wouldn't need to change the appSetting.

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

Edit

Enabling AllowAsyncDuringSyncStages or using the Task Parallel Library both have potential drawbacks. Using AsyncController does not have either drawback. Thanks @StephenCleary for challenging my answer.

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


来源:https://stackoverflow.com/questions/15098667/mvcmailer-sendasync-fails-with-amazon-ses

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!