问题
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