Reputation: 14831
I am developing an ASP.NET MVC project. I am trying to send email in background running without freezing UI. Most of the articles say now it can be done with .NET asynchronous sending email. I am sending asynchronous email but it is still freezing the UI. What I am doing is I register entering email and password then send verification email in the background. My sending email code is below.
I have interface like this.
public interface IMailHelper
{
Task SendEmailAsync(string to, string subject, string body, bool isHtml = true);
}
This is the interface implementation with send-email method
public class MailHelper : IMailHelper
{
private string EmailAddress { get; set; }
private string EmailPassword { get; set; }
private int Port { get; set; }
private string Host { get; set; }
public MailHelper()
{
this.EmailAddress = AppConfig.SystemEmailAddress;
this.EmailPassword = AppConfig.SystemEmailPassword;
this.Port = AppConfig.SystemMailPort;
this.Host = AppConfig.SystemMailHost;
}
public async Task SendEmailAsync(string to, string subject, string body, bool isHtml = true)
{
var mail = new MailMessage();
mail.To.Add(to);
mail.From = new MailAddress(this.EmailAddress);
mail.Subject = subject;
mail.Body = body;
mail.IsBodyHtml = isHtml;
using (var smtp = new SmtpClient())
{
var credential = new NetworkCredential
{
UserName = this.EmailAddress,
Password = this.EmailPassword
};
smtp.UseDefaultCredentials = false;
smtp.Credentials = credential;
smtp.Host = this.Host;
smtp.Port = this.Port;
smtp.EnableSsl = true;
await smtp.SendMailAsync(mail);
}
}
}
As you can see I am sending asynchronous email.
This is my action method in controller
[HttpPost]
[AllowAnonymous]
//[AngularValidateAntiForgeryToken]
public async Task<JsonResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
//Do other stuffs here
await _mailHelper.SendEmailAsync(user.Email, AppConfig.AccountVerifyMailSubject, WebHelper.BuildAccountVerificationEmailBody(user.UserName, verificationUrl));
}
// Do other stuffs here
}
As you can see I am trying to send email in background in the action method. My code is sending email successfully. But I am sure it is freezing the UI because it take longer than it should be. I tested many times. Not different with sending email normally. Why it is freezing the UI? My code is not sending background email in new process.
Upvotes: 0
Views: 605
Reputation: 457207
Most of the articles say now it can be done with .NET asynchronous sending email.
Those articles are all wrong, sorry.
I have a blog post that goes into various implementations of ASP.NET background tasks. In summary, if you don't care that emails are occasionally lost, then you can just use HostingEnvironment.QueueBackgroundWorkItem
:
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
...
HostingEnvironment.QueueUserWorkItem(_ =>
_mailHelper.SendEmailAsync(user.Email, AppConfig.AccountVerifyMailSubject, WebHelper.BuildAccountVerificationEmailBody(user.UserName, verificationUrl));
}
...
}
If you do care that emails are not lost, then you'll have to place them in some sort of reliable queue (Azure Queue, or MSMQ) and have an independent background worker send the actual email (Azure Function / WebJob / Worker Role, or Win32 service).
Upvotes: 1