2

I'm implementing the new version of ASP.NET Identity 2.0 that was released a week ago.

The IdentityConfig.cs is doing its job well and the user's information is added to the database and an an Email is sent to the user for confirmation. All is fine, however this error is fired unnecessarily (it sounds like a race between scripts). It's only fired when I use the Email service:

 An asynchronous module or handler completed while an asynchronous operation was still pending

The code behind is the following:

 public class EmailService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        var mailMessage = new MailMessage(
           "******@d******.com",
           message.Destination,
           message.Subject,
           message.Body
           );

        // Send the message
        SmtpClient client = new SmtpClient();
        client.SendAsync(mailMessage, null);
        return Task.FromResult(0);
    }
}

How can I solve this?

Thanks in advance.

G

Gloria
  • 1,305
  • 5
  • 22
  • 57
  • What does the code look like that calls this SendAsync method? May be similar to this QA http://stackoverflow.com/questions/22797845/asp-net-identity-2-0-how-to-implement-iidentitymessageservice-to-do-async-smtp – Kevin Junghans Apr 02 '14 at 12:50

3 Answers3

0

SendAsync() needs to be awaited...

public async Task SendAsync(IdentityMessage message)
{
    var mailMessage = new MailMessage(
       "******@d******.com",
       message.Destination,
       message.Subject,
       message.Body
       );

    // Send the message
    SmtpClient client = new SmtpClient();
    await client.SendMailAsync(mailMessage);
}
Anthony Chu
  • 37,170
  • 10
  • 81
  • 71
0

When you call client.SendAsync it starts a thread in the background to send the email, but your method returns a task that completes immediately. This exception is thrown because you should have some sort of synchronization to make sure the task you return does not complete before the background thread sending the email completes.

However, you don't need to create a background process in the first place. Your method is already asynchronous so the calling method will block until it is completed. Just can just use Send instead of SendAsync. You should also be using a using block to make sure your SMTP client is disposed correctly.

Here's an example implementation:

public class EmailService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        var mailMessage = new MailMessage(...);

        return Task.Run(() =>
        {
            using (var client = new SmtpClient())
            {
                try
                {
                    client.Send(mailMessage);
                }
                catch(Exception e)
                {
                    //log error
                    throw;
                }
            }
        });
    }
}
mark.monteiro
  • 2,609
  • 2
  • 33
  • 38
-1

Change the line:

client.SendAsync(mailMessage, null);

to:

client.Send(mailMessage);
Justin Saraceno
  • 2,516
  • 1
  • 18
  • 16