Reputation: 466
In ASP.NET Core 2.1 I have a class to send e-mail that uses IOptions interface as shown bellow:
public class Email
{
private readonly ManuelaIbiEmail manuelaIbiEmail;
public Email(IOptions<ManuelaIbiEmail> manuelaIbiEmail)
{
this.manuelaIbiEmail.Username = manuelaIbiEmail.Value.Username;
this.manuelaIbiEmail.Password = manuelaIbiEmail.Value.Password;
}
public async Task SendAsync(Contato contato)
{
var smtpClient = new SmtpClient
{
Host = "smtp.sendgrid.net",
Port = 587,
EnableSsl = true,
Credentials = new NetworkCredential(manuelaIbiEmail.Username, manuelaIbiEmail.Password)
};
using (var message = new MailMessage(contato.Email, "[email protected]")
{
Subject = "Email de Manuela Ibi Nutrição Integrada",
Body = $"{contato.Comentario}\nTelefone: {contato.Telefone}"
})
{
await smtpClient.SendMailAsync(message);
}
}
}
This class has to be instantiated in the controller with a line like "var whatever = new Email(???);" in order that the SendAsync method can be called.
But the big picture here is that I'm lost in this initialization. I just don't know what to call in "Email(something)".
Just, giving a little more information in case is needed:
The system should read the username, password from Secrets and thus I have the following line in Startup.cs:
services.Configure<ManuelaIbiEmail>(Configuration.GetSection("ManuelaIbiEmail"));
The ManuelaIbiEmail is a very simple POCO class:
public class ManuelaIbiEmail
{
public string Username { get; set; }
public string Password { get; set; }
}
The controller looks like:
public class ContactController : Controller
{
private readonly ManuelaIbiEmail manuelaIbiEmail;
public IActionResult Contact()
{
return View(new Contato());
}
[HttpPost]
public async Task<IActionResult> ContactAsync(Contato contato)
{
var email = new Email();
email.SendAsync(contato);
return Ok();
}
}
If anyone can be kind enough to tell me what I am missing, I'd appreciate.
Thank you in advance
Upvotes: 3
Views: 1469
Reputation: 247283
Ideally you do not want to tightly couple your controller to implementation concerns by manually initializing the Email
as classes should depend on abstractions and not concretions.
Abstract the email class
public interface IEmail {
Task SendAsync(Contato contato);
}
public class Email: IEmail {
//...omitted for brevity
}
and you could inject it into the controller via constructor injection
public class ContactController : Controller {
private readonly IEmail email;
public ContactController(IEmail email) {
this.email = email;
}
public IActionResult Contact() {
return View(new Contato());
}
[HttpPost]
public async Task<IActionResult> ContactAsync(Contato contato) {
await email.SendAsync(contato);
return Ok();
}
}
Once configured correctly
services.AddTransient<IEmail, Email>();
the container will resolve all dependencies while creating the object graph for injection.
Upvotes: 1
Reputation: 233192
Just inject Email
via the constructor:
public class ContactController : Controller
{
public ContactController(Email email)
{
Email = email;
}
public Email Email { get; }
public IActionResult Contact()
{
return View(new Contato());
}
[HttpPost]
public async Task<IActionResult> ContactAsync(Contato contato)
{
Email.SendAsync(contato);
return Ok();
}
}
Upvotes: 1
Reputation: 7204
My proposition :
Create a IOption
instance and init your class Email with this instance
using Microsoft.Extensions.Options;
var mail = new ManuelaIbiEmail() { Username= "", Password="" };
IOptions<ManuelaIbiEmail> options = Options.Create(mail);
var email = new Email(options);
Upvotes: -1
Reputation: 77304
The whole point of dependency injection is to not do that.
You can inject it either in the method via attributes:
public class ContactController : Controller
{
public IActionResult Contact()
{
return View(new Contato());
}
[HttpPost]
public async Task<IActionResult> ContactAsync(Contato contato, [FromServices]Email email)
{
email.SendAsync(contato);
return Ok();
}
}
Or through constructor injection:
public class ContactController : Controller
{
private readonly EMail email;
public ContactController(Email email)
{
this.email = email;
}
public IActionResult Contact()
{
return View(new Contato());
}
[HttpPost]
public async Task<IActionResult> ContactAsync(Contato contato)
{
email.SendAsync(contato);
return Ok();
}
}
Upvotes: 4