Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC with Async Action

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

like image 676
Luiz Negrini Avatar asked Jan 16 '17 03:01

Luiz Negrini


People also ask

Should I use async controller actions?

When to use Asynchronous Controller. Asynchronous action methods are useful when an action must perform several independent long running operations. Suppose we have three operations which takes 500, 600 and 700 milliseconds. With the synchronous call, total response time would be slightly more than 1800 milliseconds.

What is the use of Async controllers in MVC?

There are some massive benefits to using Asynchronous Controllers with MVC. If your application is I/O or network limited, adding an Asynchronous Controller can help your application stay responsive. It's also a really sexy way of handling long running operations without blocking your application.

When would you use asynchronous actions?

Asynchronous actions are best when your method is I/O, network-bound, or long-running and parallelizable. Another benefit of an asynchronous action is that it can be more easily canceled by the user than a synchronous request.


1 Answers

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.

like image 166
Luiz Negrini Avatar answered Sep 24 '22 14:09

Luiz Negrini