tag nswag net asp c# asp.net-core asp.net-core-mvc

c# - nswag - ¿Cómo accedo a Configuración en cualquier clase en ASP.NET Core?



tag helpers asp net core (8)

He revisado la documentación de configuración en el núcleo de ASP.NET. La documentación dice que puede acceder a la configuración desde cualquier lugar de la aplicación.

A continuación se muestra Startup.cs creado por plantilla

public class Startup { public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); if (env.IsEnvironment("Development")) { // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately. builder.AddApplicationInsightsSettings(developerMode: true); } builder.AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfigurationRoot Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddApplicationInsightsTelemetry(Configuration); services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseApplicationInsightsRequestTelemetry(); app.UseApplicationInsightsExceptionTelemetry(); app.UseMvc(); } }

Entonces, en Startup.cs configuramos todas las configuraciones, Startup.cs también tiene una propiedad llamada Configuration

¿Qué no puedo entender cómo accede a esta configuración en el controlador o en cualquier lugar de la aplicación? MS recomienda usar el patrón de opciones, pero solo tengo 4-5 pares clave-valor, por lo que me gustaría no usar el patrón de opciones. Solo quería tener acceso a Configuración en la aplicación. ¿Cómo lo inyecto en cualquier clase?


La forma correcta de hacerlo:

En .NET Core puede inyectar la IConfiguration como parámetro en su constructor de Clase, y estará disponible.

public class MyClass { private IConfiguration configuration; public MyClass(IConfiguration configuration) { ConnectionString = new configuration.GetValue<string>("ConnectionString"); }

Ahora, cuando desee crear una instancia de su clase, ya que su clase está inyectando la IConfiguration , no podrá simplemente hacer un new MyClass() , porque necesitará pasar el parámetro IConfiguration al constructor, entonces, necesitará inyectar su clase también en la cadena de inyección, lo que significa dos pasos simples:

1) Agregue su / s clase / s - donde quiera usar IConfiguration , a IServiceCollection en el método ConfigureServices() en Startup.cs

services.AddTransient<MyClass>();

2) Defina una instancia, digamos en el Controller , e inyecte usando el constructor:

public class MyController : ControllerBase { private MyClass _myClass; public MyController(MyClass myClass) { _myClass = myClass; }

Ahora debería poder disfrutar de su _myClass.configuration libremente ...

Otra opción:

Si todavía está buscando una manera de tenerlo disponible sin tener que inyectar las clases en el controlador, puede almacenarlo en una static class , que configurará en Startup.cs , algo así como:

public static class MyAppData { public static IConfiguration Configuration; }

Y su constructor de Startup debería verse así:

public Startup(IConfiguration configuration) { Configuration = configuration; MyAppData.Configuration = configuration; }

Luego use MyAppData.Configuration en cualquier parte de su programa.

No me enfrente por qué la primera opción es la correcta, solo puedo ver que los desarrolladores experimentados siempre evitan los datos basura en su camino, y se entiende que no es la mejor práctica tener un montón de datos disponibles en la memoria todo el tiempo, ni es bueno para el rendimiento ni para el desarrollo, y tal vez también sea más seguro tener solo lo que necesita.


Actualizar

El uso de ASP.NET Core 2.0 agregará automatically la instancia de IConfiguration de su aplicación en el contenedor de inyección de dependencia. Esto también funciona junto con ConfigureAppConfiguration en WebHostBuilder .

Por ejemplo:

public static void Main(string[] args) { var host = WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration(builder => { builder.AddIniFile("foo.ini"); }) .UseStartup<Startup>() .Build(); host.Run(); }

Es tan fácil como agregar la instancia de IConfiguration a la colección de servicios como un objeto único en ConfigureServices :

public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IConfiguration>(Configuration); // ... }

Donde Configuration es la instancia en su clase de Startup .

Esto le permite inyectar IConfiguration en cualquier controlador o servicio:

public class HomeController { public HomeController(IConfiguration configuration) { // Use IConfiguration instance } }


En 8-2017, Microsoft lanzó System.Configuration para .NET CORE v4.4. Actualmente v4.5 y v4.6 vista previa.

Para aquellos de nosotros, que trabajamos en la transformación de .Net Framework a CORE, esto es esencial. Permite mantener y usar los archivos actuales de app.config , a los que se puede acceder desde cualquier ensamblaje. Probablemente incluso sea una alternativa a appsettings.json , ya que Microsoft se dio cuenta de la necesidad. Funciona igual que antes en FW. Hay una diferencia:

En las aplicaciones web, [p. Ej., ASP.NET CORE WEB API] debe usar app.config y no web.config para su configurationSection appSettings o configurationSection . Es posible que deba usar web.config pero solo si implementa su sitio a través de IIS. Coloca configuraciones específicas de IIS en web.config

Lo probé con netstandard20 DLL y Asp.net Core Web Api y todo funciona.


Lo estoy haciendo así en este momento:

// Requires NuGet package Microsoft.Extensions.Configuration.Json using Microsoft.Extensions.Configuration; using System.IO; namespace ImagesToMssql.AppsettingsJson { public static class AppSettingsJson { public static IConfigurationRoot GetAppSettings() { string applicationExeDirectory = ApplicationExeDirectory(); var builder = new ConfigurationBuilder() .SetBasePath(applicationExeDirectory) .AddJsonFile("appsettings.json"); return builder.Build(); } private static string ApplicationExeDirectory() { var location = System.Reflection.Assembly.GetExecutingAssembly().Location; var appRoot = Path.GetDirectoryName(location); return appRoot; } } }

Y luego uso esto donde necesito obtener los datos del archivo appsettings.json:

var appSettingsJson = AppSettingsJson.GetAppSettings(); // appSettingsJson["keyName"]


Miré la muestra del patrón de opciones y vi esto:

public class Startup { public Startup(IConfiguration config) { // Configuration from appsettings.json has already been loaded by // CreateDefaultBuilder on WebHost in Program.cs. Use DI to load // the configuration into the Configuration property. Configuration = config; } ... }

Al agregar Iconfiguration en el constructor de mi clase, pude acceder a las opciones de configuración a través de DI.

Ejemplo:

public class MyClass{ private Iconfiguration _config; public MyClass(Iconfiguration config){ _config = config; } ... // access _config["myAppSetting"] anywhere in this class }


Sé que esto es antiguo, pero dados los patrones de IOptions es relativamente simple de implementar:

  1. Clase con propiedades públicas get / set que coinciden con la configuración en la configuración

    public class ApplicationSettings { public string UrlBasePath { get; set; } }

  2. registre su configuración

    public void ConfigureServices(IServiceCollection services) { ... services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings")); ... }

  3. inyectar a través de IOptions

    public class HomeController { public HomeController(IOptions<ApplicationSettings> appSettings) { ... appSettings.Value.UrlBasePath ... // or better practice create a readonly private reference } }

No estoy seguro de por qué no harías esto.


También hay una opción para hacer que la configuration estática en startup.cs para que pueda acceder a ella desde cualquier lugar con facilidad, las variables estáticas son convenientes, ¿eh?

public Startup(IConfiguration configuration) { Configuration = configuration; } internal static IConfiguration Configuration { get; private set; }

Esto hace que la configuración sea accesible desde cualquier lugar usando Startup.Configuration.GetSection... ¿Qué puede salir mal?


Tengo que leer los propios parámetros al inicio.
Eso tiene que estar allí antes de que se inicie WebHost (ya que necesito la url / IP "para escuchar" y el puerto del archivo de parámetros y aplicarlo a WebHost). Además, necesito la configuración pública en toda la aplicación.

Después de buscar durante un tiempo (no se encontró un ejemplo completo, solo fragmentos) y después de varios intentos y errores, decidí hacerlo "a la antigua usanza" con un archivo .ini propio.
Entonces ... si desea usar su propio archivo .ini y / o configurar el "escuchar url / IP" y / o necesita la configuración pública, esto es para usted ...

Ejemplo completo, válido para core 2.1 (mvc):

Crear un archivo .ini - ejemplo:

[Puesta en marcha]
URL = http://172.16.1.201:22222
[Parámetro]
* Dummy1 = gew7623
Dummy1 = verdadero
Dummy2 = 1

por lo que los Dummyx solo se incluyen como ejemplo para otros tipos de fechas que no sean cadenas (y también para probar el caso "parámetro incorrecto" (ver código a continuación).

Se agregó un archivo de código en la raíz del proyecto, para almacenar las variables globales:

namespace MatrixGuide { public static class GV { // In this class all gobals are defined static string _cURL; public static string cURL // URL (IP + Port) on that the application has to listen { get { return _cURL; } set { _cURL = value; } } static bool _bdummy1; public static bool bdummy1 // { get { return _bdummy1; } set { _bdummy1 = value; } } static int _idummy1; public static int idummy1 // { get { return _idummy1; } set { _idummy1 = value; } } static bool _bFehler_Ini; public static bool bFehler_Ini // { get { return _bFehler_Ini; } set { _bFehler_Ini = value; } } // add further GV variables here.. } // Add further classes here... }

Cambió el código en program.cs (antes de CreateWebHostBuilder ()):

namespace MatrixGuide { public class Program { public static void Main(string[] args) { // Read .ini file and overtake the contend in globale // Do it in an try-catch to be able to react to errors GV.bFehler_Ini = false; try { var iniconfig = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddIniFile("matrixGuide.ini", optional: false, reloadOnChange: true) .Build(); string cURL = iniconfig.GetValue<string>("Startup:URL"); bool bdummy1 = iniconfig.GetValue<bool>("Parameter:Dummy1"); int idummy2 = iniconfig.GetValue<int>("Parameter:Dummy2"); // GV.cURL = cURL; GV.bdummy1 = bdummy1; GV.idummy1 = idummy2; } catch (Exception e) { GV.bFehler_Ini = true; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("!! Fehler beim Lesen von MatrixGuide.ini !!"); Console.WriteLine("Message:" + e.Message); if (!(e.InnerException != null)) { Console.WriteLine("InnerException: " + e.InnerException.ToString()); } Console.ForegroundColor = ConsoleColor.White; } // End .ini file processing // CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() //; .UseUrls(GV.cURL, "http://localhost:5000"); // set the to use URL from .ini -> no impact to IISExpress } }

De esta manera:

  • La configuración de mi aplicación está separada de appsettings.json y no tengo efectos secundarios que temer, si MS cambia en versiones futuras ;-)
  • Tengo mi configuración en variables globales
  • Puedo configurar la "url de escucha" para cada dispositivo, la aplicación se ejecuta (mi máquina de desarrollo, el servidor de intranet y el servidor de internet)
  • Puedo desactivar la configuración, a la antigua usanza (solo establezca un * antes)
  • Soy capaz de reaccionar, si algo está mal en el archivo .ini (por ejemplo, no coinciden los tipos)
    Si, por ejemplo, se establece un tipo incorrecto (por ejemplo, * Dummy1 = gew7623 está activado en lugar de Dummy1 = true), el host muestra información roja en la consola (incluida la excepción) y puedo reaccionar también en la aplicación (GV .bFehler_Ini se establece en verdadero, si hay errores con el .ini)