MVCMailer SendAsync()失败与亚马逊SES(MVCMailer SendAsync

2019-07-20 13:50发布

如果我使用的send()与MVCMailer,我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)

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


文章来源: MVCMailer SendAsync() fails with Amazon SES