382 messaggi dal 26 agosto 2007
Ciao a tutti,
è da poco che sto cominciando a lavorare con il .NET Core e non riesco a capire come fare ad accedere ai valori presenti nel file appsettings.json da una classe qualsiasi. In rete ho trovato decine di esempi su come utilizzare la DI sui controller MVC ma nessun esempio di come recuperare questi valori da una classe che non sia un controller.
Come devo fare?

Lunga vita e prosperità!!
10.806 messaggi dal 09 febbraio 2002
Contributi
Ciao,


a capire come fare ad accedere ai valori presenti nel file appsettings.json da una classe qualsiasi

C'è una soluzione brutta e perciò non te la dico. Quello che dovresti fare, invece, è registrare la tua "classe qualsiasi" come servizio nel meccanismo di dependency injection di ASP.NET Core.

Supponiamo che tu abbia una classe SmtpClient che usi per inviare le email e che internamente necessita dei valori di configurazione situati nel file appsettings.json (es. nome host, porta, user, password, ecc..). Per prima cosa, estrai un'interfaccia che servirà a migliorare il disaccoppiamento tra i componenti e perciò aumenterà la testabilità della tua applicazione.
public interface ISmtpClient {
  Task SendMail(string to, string subject, string body);
}


Ora fai implementare questa interfaccia alla tua classe. Inoltre, nota come nel costruttore della classe SmtpClient ho esplicitato una dipendenza da IOptionsMonitor<SmtpOptions>, un servizio che ti permette di recuperare la configurazione corrente (si aggiorna dopo eventuali modifiche a caldo apportate all'appsettings.json) e che verrà iniettato dalla dependency injection di ASP.NET Core.
public class SmtpClient : ISmtpClient {
   private readonly IOptionsMonitor<SmtpOptions> smtpOptions
   public SmtpClient(IOptionsMonitor<SmtpOptions> smtpOptions) {
      this.smtpOptions = smtpOption;
   }
   
   public async Task SendMail(string to, string subject, string body) {
     //Accedo alla configurazione
     //Prima ottengo la configurazione attuale dal monitor
     var config = smtpOptions.CurrentValue;
     //E poi leggo i singoli valori
     var host = config.Host;
     var port = config.Port;
     var username = config.Username;
     var password = config.Password;
     var useSSL = config.UseSSL;

     //Implementazione di invio email qui, usando i parametri ottenuti dalla configurazione
   }
}


La classe SmtpOptions che ho menzionato nell'esempio qui sopra è una classe personalizzata che riflette la struttura di un ramo dell'appsettings.json. Supponiamo che l'appsettings.json sia fatto così:
{
   "Smtp": {
     "Host": "smtp.example.com",
     "Port": 25,
     "Username": "Pippo",
     "Password": "Puppo",
     "UseSSL": false
   },
   "AltraProprietà": "Whatever",
   ...
}

Allora la classe chiamata (ad esempio) SmtpOptions avrà queste proprietà, che riflettono tali e quali il nome e il tipo di dati trovati nel json. Io la creo a mano ma da Visual Studio te la puoi anche creare velocemente dal menu Modifica -> Incolla speciale -> Incolla JSON come classi, dopo aver copiato il json ovviamente.
public class SmtpOptions {
  public string Host { get; set; }
  public int Port { get; set; }
  public string Username { get; set; }
  public string Password { get; set; }
  public bool UseSSL { get; set; }
}


Adesso è il momento di tirare le fila: tutto quanto va registrato come servizio dal metodo ConfigureServices della classe Startup.
public void ConfigureServices(IServiceCollection services)
{
  ...
  //Registro l'SmtpClient come servizio
  services.AddTransient<ISmtpClient, SmtpClient>();
  //Registro la configurazione per SmtpOptions, che mi permetterà di usare il servizio IOptionsMonitor
  services.Configure<SmtpOptions>(Configuration.GetSection("Smtp"));
  ...
}


A questo punto, ora che il servizio ISmtpClient è stato registrato, lo puoi ricevere come parametro del costruttore di un qualsiasi altro componente dell'applicazione, come: Controller, Middleware, View (meglio non inviare un'email da una view, ma tant'è), Hosted Service e qualsiasi altro servizio che sia stato esso stesso registrato con la dependency injection.

ciao,
Moreno
Modificato da BrightSoul il 18 luglio 2018 21.59 -

Enjoy learning and just keep making
382 messaggi dal 26 agosto 2007
Ciao e grazie mille per la risposta, molto chiara! Forse però c'è ancora una cosa che mi sfugge.. Registrando la classe SmtpClient come servizio nella DI, come faccio a richiamarla da altre classi per poter inviare l'email?

Lunga vita e prosperità!!
10.806 messaggi dal 09 febbraio 2002
Contributi
Ciao, prego!


come faccio a richiamarla da altre classi per poter inviare l'email?

Anche le altre classi diventano servizi da registrare nel metodo ConfigureServices.

Ripeto:

lo puoi ricevere come parametro del costruttore di un qualsiasi altro componente dell'applicazione, come: Controller, Middleware, ...


Quindi ad esempio:
public OrderController : Controller {

  private readonly ISmtpClient smtpClient;
  public OrderController(ISmtpClient smtpClient) {
     this.smtpClient = smtpClient;
  }

  public async Task<IActionResult> Order(OrderModel model) {
     ...
     await smtpClient.SendMail(model.Email, "Ordine ricevuto", "Abbiamo ricevuto il tuo ordine");
     ...
  }
}


Oppure, se hai bisogno del servizio solo in una particolare action, lo puoi ricevere direttamente come parametro di quell'action grazie all'attributo [FromServices]
public OrderController : Controller {

  public async Task<IActionResult> Order(OrderModel model, [FromServices] ISmtpClient smtpClient) {
     ...
     await smtpClient.SendMail(model.Email, "Ordine ricevuto", "Abbiamo ricevuto il tuo ordine");
     ...
  }
}


Se la tua elaborazione non inizia da un Controller, comunque inizierà da un Middleware o da un job in background. In ogni caso, hai il supporto alla dependency injection e quindi puoi procurarti i servizi come parametri del costruttore

ciao,
Moreno
Modificato da BrightSoul il 18 luglio 2018 22.52 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.