14

I need to send an asynchronous email from an Async action. I do not understand why the following error is happening, being that I use this same class in other projects and use the same form only without errors, everything quiet.

Error:

The asynchronous action method 'EsqueciMinhaSenhaAsync' returns a Task, which cannot be executed synchronously.

Action:

        [AllowAnonymous]
        [HttpPost, ValidateAntiForgeryToken]
        public async Task<ActionResult> EsqueciMinhaSenhaAsync(UsuarioEsqueciMinhaSenhaViewModel vModel)
        {
            if (ModelState.IsValid)
            {
                var conteudo = "este é o conteudo do email";
                var nomeRemetente = "esse é o nome do remetente";

                if(await EmailService.SendAsync(Language.PasswordRecovery, conteudo, vModel.EmailOuUsername, nomeRemetente))
                {
                    TempData["MensagemRetorno"] = Language.EmailSendedWithSuccess;
                    return View("login");
                }
            }

            TempData["MensagemRetorno"] = Language.ErrorSendingEmail;
            return View("EsqueciMinhaSenha");
        }

My Email Service:

    public static async Task<bool> SendAsync(string assunto, string conteudo, string destinatario, string nomeDestinatario)
    {
        // Habilitar o envio de e-mail
        var appSetting = ConfigurationManager.AppSettings;

        if (appSetting != null && appSetting.Count >= 7 && !string.IsNullOrEmpty(assunto) && !string.IsNullOrEmpty(conteudo) && !string.IsNullOrEmpty(destinatario) && !string.IsNullOrEmpty(nomeDestinatario))
        {
            int port = 0;
            bool useSSl = false;

            using (var msg = new MailMessage
            {
                From = new MailAddress(appSetting["EmailFrom"], appSetting["EmailNameFrom"]),
                Body = WebUtility.HtmlEncode(conteudo)
            })
            {
                int.TryParse(appSetting["EmailPort"], out port);
                bool.TryParse(appSetting["EmailUseSSL"], out useSSl);


                msg.ReplyToList.Add(destinatario);
                msg.To.Add(new MailAddress(destinatario, nomeDestinatario));
                msg.Subject = assunto;
                msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(msg.Body, null, MediaTypeNames.Text.Plain));
                msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(msg.Body, null, MediaTypeNames.Text.Html));

                using (var smtpClient = new SmtpClient(appSetting["EmailServer"], port))
                {
                    var credentials = new NetworkCredential(appSetting["EmailUserName"], appSetting["EmailPassword"]);
                    smtpClient.Credentials = credentials;
                    smtpClient.EnableSsl = useSSl;
                    await smtpClient.SendMailAsync(msg);

                    return await Task.FromResult(true);
                }
            }
        }

        return await Task.FromResult(false);
    }

Stack Trace:

[InvalidOperationException: The asynchronous action method 'esqueciminhasenha' returns a Task, which cannot be executed synchronously.]
System.Web.Mvc.Async.TaskAsyncActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +119
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2 parameters) +27
System.Web.Mvc.<>c__DisplayClass15.b__12() +55 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +253
System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList
1 filters, ActionDescriptor actionDescriptor, IDictionary2 parameters) +189
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +521
System.Web.Mvc.Controller.ExecuteCore() +95
MusiArtist.MVC.Areas.admin.Controllers.BaseController.ExecuteCore() in F:\Backup\BitBucket\negrini.musiartist\src\MusiArtist.MVC\Areas\admin\Controllers\BaseController.cs:29 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +180 System.Web.Mvc.<>c__DisplayClass19.<BeginExecute>b__13() +18 System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action) +15
System.Web.Mvc.Async.WrappedAsyncResult
2.CallEndDelegate(IAsyncResult asyncResult) +16
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
System.Web.Mvc.Async.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9765121 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Luiz Negrini
  • 656
  • 10
  • 32
  • replace `await Task.FromResult` with just `true` or `false` in the email service – Nkosi Jan 16 '17 at 03:44
  • @Nkosi same error =/ – Luiz Negrini Jan 16 '17 at 03:46
  • Check http://stackoverflow.com/questions/14994335/the-asynchronous-action-method-returns-a-task-which-cannot-be-executed-synchron – Nkosi Jan 16 '17 at 03:47
  • @Nkosi 276/5000 As I said, I have always used this in other projects and I had no problems, I can not change my base controller as this solution says, I have my own controller base that inherits from "Controller", however the "Controller" should work, In my other projects. – Luiz Negrini Jan 16 '17 at 03:51
  • @LuizNegrini replace `await Task.FromResult` with the actual values. Awaiting for an already completed task is pointless. While it may not be the cause of the problem, it's a waste of CPU cycles and makes the code uglier; – Panagiotis Kanavos Jan 24 '17 at 16:27
  • The error complains about your action method itself, not the Email service. Please post your controller code. – Panagiotis Kanavos Jan 24 '17 at 16:33
  • Was the project upgraded from MVC 3 perhaps? [In this question](http://stackoverflow.com/questions/14994335/the-asynchronous-action-method-returns-a-task-which-cannot-be-executed-synchron) the upgrade process left some old dlls. Once they were removed, the application worked without problem – Panagiotis Kanavos Jan 24 '17 at 16:36
  • 1
    To verify that the upgrade is the problem try creating a *new* MVC project with just that single controller and action. – Panagiotis Kanavos Jan 24 '17 at 16:38
  • @PanagiotisKanavos I have said several times, in another project running the same version is working. – Luiz Negrini Jan 25 '17 at 14:24
  • @LuizNegrini which doesn't mean anything if there are leftover dlls in your production folder. Just try and verify the problem first. Don't assume that MVC 4 *and* the error message *and* every programmer that uses MVC 4 is broken. The only google results for such an error link to issues with leftover files – Panagiotis Kanavos Jan 25 '17 at 14:29
  • @LuizNegrini actually, the fact that this code works in other projects means that it's *NOT* a coding problem. Why don't you try doing a clean deployment? Or at least check the dll versions in the debug folder? You may be using an old NuGet package that added the wrong dependency – Panagiotis Kanavos Jan 25 '17 at 14:30
  • @PanagiotisKanavos It worked normally ... I created a new project and changed the index of the home controller and it worked normally, it really can be something old running, but I did not update the project for a new version, the project was already created in the same version as this one I created now to test. How do I analyze this problem and check if the dlls are the same? Is there a shortcut? – Luiz Negrini Jan 25 '17 at 14:34
  • @PanagiotisKanavos Yes, I've cleaned all debug and obj folders but it does not solve at all. – Luiz Negrini Jan 25 '17 at 14:34
  • @LuizNegrini can you post the full exception, including its call stack? Also, how do you test your code? Do you deploy to IIS or run under the dev web server? – Panagiotis Kanavos Jan 25 '17 at 14:34
  • @PanagiotisKanavos I will post, but only later, I am not at my place of work. Thank you for the support. Yes it runs in visual studio normally, without deploy some. – Luiz Negrini Jan 25 '17 at 14:56

1 Answers1

1

I made an override on the "DisableAsyncSupport" method of the Controller and set the getter to false and everything worked perfectly!!!

protected override bool DisableAsyncSupport
{
    get { return false; }
}

I believe that by inheriting from controller (I have my own controller, "ControllerBase") the method must behave differently.

Luiz Negrini
  • 656
  • 10
  • 32