Reputation: 4310
I am using ASP.NET Web Form to send two emails and once both emails are sent, I am deleting the file from the system. My code is using async/await and its working fine in the Console application but when I moved the same code to the asp.net web form, it's sending emails but I am not getting any response after Task.WaitAll(emailSender1, emailSender2), as a result, the file is not deleted and the browser is always seeing loading. I tried to fix the issue but unable at the end. I need someones help to resolve the issue or any alternate ways that could be accomplished. My code is as below:
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" Async="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnSendEmail" runat="server" Text="Send Email" OnClick="btnSendEmail_Click" />
</div>
</form>
</body>
</html>
Default.aspx.cs Code behind
using System;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private static string filePath = @"C:\Uploads\";
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSendEmail_Click(object sender, EventArgs e)
{
Sender mailSender = new Sender();
mailSender.SendEmail("[email protected]", "[email protected]", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
Response.Redirect("Succcess.apsx");
}
}
}
Sender.cs
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace WebApplication1
{
public class Sender
{
public void SendEmail(string toEmail, string logMail, string title, string body, string attachmentPath)
{
var emailSender1 = SendEmailAsync(toEmail, title, body, attachmentPath);
var emailSender2 = SendEmailAsync(logMail, "Copy of " + title, body, attachmentPath);
Task.WaitAll(emailSender1, emailSender2);
// deleting file
File.Delete(attachmentPath);
}
public async Task SendEmailAsync(string toEmail, string title, string body, string attachmentPath)
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
await smtpClient.SendMailAsync(mailMsg);
}
}
}
}
}
MailConfiguration.cs
public class MailConfiguration
{
private SmtpSection smtpSection = (ConfigurationManager.GetSection("system.net/mailSettings/smtp")) as SmtpSection;
public string ConfigurationFileName
{
get
{
try
{
return smtpSection.ElementInformation.Source;
}
catch (Exception)
{
return "";
}
}
}
public string FromAddress
{
get
{
return smtpSection.From;
}
}
public string Host
{
get
{
return smtpSection.Network.Host;
}
}
public int Port
{
get
{
return smtpSection.Network.Port;
}
}
public int TimeOut
{
get
{
return 2000;
}
}
public override string ToString()
{
return "From: [" + FromAddress + "] Host: [" + Host + "] Port: [" + Port + "]";
}
}
Upvotes: 2
Views: 933
Reputation: 4310
After going through this article I came to know that the Console application uses a thread pool SynchronizationContext while GUI or ASP.NET use a one-chunk-at-a-time SynchronizationContext. It means the major cause of deadlock was because of Task.WaitAll(emailSender1, emailSender2). According to the article, I changed this line of code to await Task.WhenAll(emailSender1, emailSender2). The corrected solution is:
Default.aspx.cs code behind
using System;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private static string filePath = @"C:\Uploads\";
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSendEmail_Click(object sender, EventArgs e)
{
Sender mailSender = new Sender();
mailSender.SendEmail("[email protected]", "[email protected]", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
Response.Redirect("Success.aspx", false);
}
}
}
Sender.cs
using System;
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace WebApplication1
{
public class Sender
{
public void SendEmail(string toEmail, string logMail, string title, string body, string attachmentPath)
{
var result = ActualEmailSend(toEmail, logMail, title, body, attachmentPath);
}
public async Task ActualEmailSend(string toEmail, string logMail, string title, string body, string attachmentPath)
{
var emailSender1 = SendEmailAsync(toEmail, title, body, attachmentPath);
var emailSender2 = SendEmailAsync(logMail, "Copy of " + title, body, attachmentPath);
await Task.WhenAll(emailSender1, emailSender2);
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
File.Delete(attachmentPath);
}
}
public async Task SendEmailAsync(string toEmail, string title, string body, string attachmentPath)
{
try
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
await smtpClient.SendMailAsync(mailMsg);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendEmail exception: " + ex);
}
finally
{
Console.WriteLine("SendEmail done");
}
}
}
}
Upvotes: 1