Im пытается отправить асинхронный почтовый ящик с litte, регистрирующимся в базе данных, когда smtpclient не удается отправить. Я использую WebAPI 2.2 + EF6 + Autofac. Ошибка говорит:DbContext удаляется после отправки почты с SmtpClient
Операция не может быть выполнена, так как был удален DbContext.
Мой главный код:
public class SMTPEmailSender : IEmailSender
{
[...]
public void SendMailAsync(string templateKey, object model, string subject, MailAddress fromAddress, List<MailAddress> toAddresses,
List<MailAddress> ccAddresses = null, List<MailAddress> replyTo = null)
{
try
{
var htmlBody = GenerateHtmlBody(templateKey, model);
var client = new SmtpClient();
var message = new MailMessage
{
From = fromAddress,
Subject = subject,
IsBodyHtml = true,
Body = htmlBody
};
toAddresses.ForEach(m => message.To.Add(m));
if (ccAddresses != null) ccAddresses.ForEach(m => message.CC.Add(m));
if (replyTo != null) replyTo.ForEach(m => message.ReplyToList.Add(m));
client.SendCompleted += SendCompletedCallback;
client.SendAsync(message, message);
}
catch (Exception ex)
{
throw new Exception("Error: " + ex.Message + "<br/><br/>Inner Exception: " + ex.InnerException);
}
}
private void SendCompletedCallback(object s, AsyncCompletedEventArgs e)
{
SmtpClient callbackClient = s as SmtpClient;
MailMessage callbackMailMessage = e.UserState as MailMessage;
var regData = SenderMailLogModel(callbackMailMessage);
if (e.Cancelled)
{
try
{
callbackClient.Send(callbackMailMessage);
}
catch (Exception ex)
{
regData.EmailSenderStatus = EmailSenderStatuses.Cancelled;
regData.Exception = ex.Message;
}
}
if (e.Error != null)
{
regData.EmailSenderStatus = EmailSenderStatuses.Error;
regData.Exception = e.Error.ToString() + " in SendCompletedHandlerEvent";
}
_dbContext.EmailSenderLogs.Add(regData); //here fails
_dbContext.SaveChanges();
callbackClient.Dispose();
callbackMailMessage.Dispose();
}
[...]
}
Мой DataContext впрыскивается Autofac. Мой контейнер конфигурации строитель:
[...]
containerBuilder.RegisterType<DbEntities>().AsSelf().InstancePerRequest();
containerBuilder.RegisterType<SMTPEmailSender>().As<IEmailSender>().InstancePerRequest();
[...]
У меня есть Hacky решение для этого, вы можете создать новый объект DbEntities и использовать его вместо autofac впрыскивается объекта.
Это происходит потому, что вы используете 'InstancePerRequest'. Это будет уничтожать «DbContext», когда «Application_EndRequest» происходит с «HttpContext», который встречается * до того, как ваша почта будет отправлена. Вам понадобится какая-то гибридная область для вашей жизни DbEntities. Не уверен, что AutoFac предлагает это, но SimpleInjector делает. http://simpleinjector.readthedocs.org/en/latest/lifetimes.html – danludwig
Autofac предлагает гибридные сроки службы. Я не знаю, как работает срок службы и утилизация. Я просто пытался перенести свои проекты на simpleinjector, кажется, проще и быстрее. – Daniel
SimpleInjector - это удовольствие работать с IMO, это отличный инструмент IoC. – danludwig