Làm cách nào để truy cập Cấu hình trong bất kỳ lớp nào trong ASP.NET Core?


127

Tôi đã đi qua tài liệu cấu hình trên lõi ASP.NET. Tài liệu nói rằng bạn có thể truy cập cấu hình từ bất cứ đâu trong ứng dụng.

Dưới đây là Startup.cs được tạo bởi mẫu

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();
    }
}

Vì vậy, trong Startup.cscấu hình tất cả các cài đặt, Startup.cs cũng có một thuộc tính có tênConfiguration

Điều tôi không thể hiểu làm thế nào để bạn truy cập cấu hình này trong bộ điều khiển hoặc bất cứ nơi nào trong ứng dụng? MS đang khuyến nghị sử dụng mẫu tùy chọn nhưng tôi chỉ có 4-5 cặp khóa-giá trị nên tôi không muốn sử dụng mẫu tùy chọn. Tôi chỉ muốn có quyền truy cập vào Cấu hình trong ứng dụng. Làm thế nào để tôi tiêm nó trong bất kỳ lớp học?


1
Nếu đó là 4-5 cặp giá trị chính thì bạn chỉ có thể tiêm các cài đặt riêng lẻ đó. Tôi khuyên bạn nên tiếp cận hoặc mẫu tùy chọn cho mục đích kiểm tra. Tất cả ba phương thức (bao gồm cả phương pháp bạn đã hỏi ban đầu) được liệt kê dưới dạng câu trả lời trong câu hỏi trùng lặp có thể có sau đây: stackoverflow.com/questions/30263681/
Kẻ

Để truy cập cấu hình như một từ điển từ bất cứ đâu, hãy kiểm tra câu trả lời này .
Amro

Kiểm tra ở đây cho ví dụ mã đầy đủ.
Arghya C

Nếu bạn đến đây vì bạn đang loay hoay với việc chuyển đổi cấu hình Framework sang cấu hình CORE, câu trả lời này là dành cho bạn stackoverflow.com/a/56498687/1704458
TS

Câu trả lời:


147

Cập nhật

Sử dụng ASP.NET Core 2.0 sẽ tự động thêm IConfigurationphiên bản ứng dụng của bạn vào thùng chứa phụ thuộc. Điều này cũng hoạt động kết hợp với ConfigureAppConfigurationtrên WebHostBuilder.

Ví dụ:

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

    host.Run();
}

Thật dễ dàng như việc thêm IConfigurationcá thể vào bộ sưu tập dịch vụ như một đối tượng đơn lẻ trong ConfigureServices:

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

   // ...
}

Trường Configurationhợp trong Startuplớp học của bạn ở đâu

Điều này cho phép bạn tiêm IConfigurationvào bất kỳ bộ điều khiển hoặc dịch vụ nào:

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

4
Mollerna .... và làm thế nào nếu bạn muốn tiêm cấu hình trong một dự án thư viện lớp riêng biệt trong giải pháp? Đã thử như thế này IConfiguration tĩnh _configuration {get; bộ; } Trình trợ giúp cơ sở dữ liệu công cộng (cấu hình IConfiguration) {_configuration = configure; } nhưng _configuration luôn là null ... nó không bao giờ bị tấn công trong trình xây dựng
dinotom

2
Điều đó nói rằng, đi xung quanh IConfigurationnhư thế là rất rò rỉ. Tốt hơn nhiều để sử dụng mẫu Tùy chọn .
Marc L.

7
Làm cách nào để truy cập trực tiếp các giá trị từ "appsinstall.json" trong một lớp tùy chỉnh? Nếu không truyền dữ liệu từ bộ điều khiển? Có thể không?
Tadej

2
@HenkMollema Bạn có thể thêm một ví dụ về nó ở đây? Làm thế nào tôi có thể tiêm nó cho bất kỳ lớp học (từ đâu?).
Tadej

5
@HenkMollema Câu hỏi là làm thế nào để tiêm vào bất kỳ lớp nào ... không phải làm thế nào để tiêm vào "bất kỳ lớp nào được giải quyết thông qua tiêm phụ thuộc". Tôi nghĩ đó là nơi thông tin sai lệch ... lớp của anh ta có thể không được gọi từ một chuỗi bắt đầu bằng Bộ điều khiển hoặc đối tượng khác được giải quyết tự động bằng quy trình DI tự động.
BVernon

34

Cách đúng đắn để làm điều đó:

Trong .NET Core, bạn có thể đưa IConfigurationtham số làm tham số vào hàm tạo Class của mình và nó sẽ có sẵn.

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

Bây giờ, khi bạn muốn tạo một thể hiện của lớp, vì lớp của bạn được tiêm IConfiguration, bạn sẽ không thể làm được new MyClass(), bởi vì nó cần một IConfigurationtham số được đưa vào hàm tạo, vì vậy, bạn sẽ cần tiêm lớp của bạn như cũng theo chuỗi tiêm, có nghĩa là hai bước đơn giản:

1) Thêm Lớp / es của bạn - nơi bạn muốn sử dụng IConfiguration, IServiceCollectionvào ConfigureServices()phương thức trongStartup.cs

services.AddTransient<MyClass>();

2) Xác định một thể hiện - giả sử trong Controllervà tiêm nó bằng cách sử dụng hàm tạo:

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

Bây giờ bạn có thể tận hưởng một _myClass.configurationcách tự do ...

Một lựa chọn khác:

Nếu bạn vẫn đang tìm cách để có sẵn nó mà không cần phải chèn các lớp vào bộ điều khiển, thì bạn có thể lưu trữ nó trong một static class, mà bạn sẽ cấu hình trong Startup.cs, đại loại như:

public static class MyAppData
{
    public static IConfiguration Configuration;
}

Và nhà Startupxây dựng của bạn sẽ trông như thế này:

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

Sau đó sử dụng MyAppData.Configurationbất cứ nơi nào trong chương trình của bạn.

Đừng đối mặt với tôi tại sao tùy chọn đầu tiên là đúng cách, tôi chỉ có thể thấy các nhà phát triển có kinh nghiệm luôn tránh dữ liệu rác theo cách của họ và hiểu rõ rằng đó không phải là cách tốt nhất để có sẵn vô số dữ liệu trong bộ nhớ, nó không tốt cho hiệu suất và cũng không phải để phát triển, và có lẽ nó cũng an toàn hơn khi chỉ có với bạn những gì bạn cần.


5
Tất cả việc tiêm các tệp cấu hình này có vẻ hơi vô nghĩa / lộn xộn. TY cho ý tưởng lớp cấu hình tĩnh.
Andrew

1
Câu hỏi, tất nhiên là về việc truy cập cấu hình trong bất kỳ lớp nào và không chỉ bộ điều khiển. Và trong khi với sự phát triển mới của dịch vụ nạc (microservice) thì điều này có thể được nghĩ đến, khi nói đến việc di chuyển, đây là một nỗi đau lớn. Đây là lý do tại sao microsoft đã System.Configurationcho CORE trở lại đúng hướng. Bây giờ, bạn có thể truy cập app.configs cũ tốt như thời xưa. Và tôi không nói chuyện điều khiển ở đây. Chúng ta đang nói về các thành phần có cấu hình riêng
TS

Nó cho phép truy cập trong bất kỳ lớp nào và không chỉ trong bộ điều khiển, nó chỉ cần được nhập vào bộ điều khiển để có được phép tiêm phụ thuộc.
Mayer Spitzer

1
Theo tôi, phương pháp này hoạt động và các lý lẽ cho hoặc chống lại mỗi phương pháp đều mang tính học thuật. Tôi đã sử dụng cả hai cho các ứng dụng khác nhau ... bây giờ, nhờ vào tùy chọn thứ hai cực kỳ dễ dàng của bạn. Tạo một lớp tĩnh khá khó khăn khi sử dụng DI.
iGanja

Phương thức thứ hai cũng giúp giải quyết một vấn đề phổ biến trong .Net Core 2.0 - các đối tượng được khởi tạo dưới dạng tham số POST (nghĩa là tự động khử từ JSON), trong đó bạn không có cơ hội đưa vào hàm tạo (ít nhất là không có nhiều mã phụ). Điều này hoạt động rất tốt cho kịch bản đó
Joe Moon

30

Tôi biết điều này đã cũ nhưng được đưa ra các mẫu IOptions tương đối đơn giản để thực hiện:

  1. Lớp có thuộc tính get / set công khai khớp với các cài đặt trong cấu hình

    public class ApplicationSettings
    {
        public string UrlBasePath { get; set; }
    }
  2. đăng ký cài đặt của bạn

    public void ConfigureServices(IServiceCollection services)
    {
     ...
     services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
    ...
    }
  3. tiêm qua IOptions

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

Tôi không chắc tại sao bạn sẽ không làm điều này.



2
Làm cách nào để truy cập trực tiếp các giá trị từ "appsinstall.json" trong một lớp tùy chỉnh?
Tadej

2
@JedatKinports bạn cần thêm các phụ thuộc Nuget Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.BinderMicrosoft.Extensions.Configuration.Jsonsau đó bạn tải appsettings.jsontệp như var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();.. và bạn cũng phải đảm bảo appsettings.jsonsao chép vào thư mục đầu ra được đặt thànhcopy always
LP13

7

Ngoài ra còn có một tùy chọn để tạo configurationtĩnh trong startup.cs để những gì bạn có thể truy cập ở bất cứ đâu một cách dễ dàng, các biến tĩnh đều thuận tiện huh!

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

internal static IConfiguration Configuration { get; private set; }

Điều này làm cho cấu hình có thể truy cập ở bất cứ đâu bằng cách sử dụng Startup.Configuration.GetSection...Điều gì có thể sai?


6

Tôi đang làm nó như thế này vào lúc này:

// 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;
        }
    }
}

Và sau đó tôi sử dụng cái này khi tôi cần lấy dữ liệu từ tệp appsinstall.json:

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

3

Tôi nhìn vào mẫu mẫu tùy chọn và thấy điều này:

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;
    }
...
}

Khi thêm Iconfiguration trong hàm tạo của lớp, tôi có thể truy cập các tùy chọn cấu hình thông qua DI.

Thí dụ:

public class MyClass{

    private Iconfiguration _config;

    public MyClass(Iconfiguration config){
        _config = config;
    }

    ... // access _config["myAppSetting"] anywhere in this class
}

Nó có hoạt động mà không đề cập rõ ràng đến MyClass trong Startup.cs, một cái gì đó như thế này không? services.AddTransient <MyClass> ();
Bố già

Vâng, thực sự, bạn nên đề cập đến các lớp bạn muốn tiêm trong Startup.cs, chứ không phải theo cách khác. Nhưng IConfiguration theo tôi mặc định đã có sẵn để tiêm.
Pieter Heemeryck

Có nó hoạt động. Tôi đã thử điều này sau khi thực hiện nhận xét và cấu hình đã được đưa vào trong IConfiguration. Dù sao cũng cảm ơn :)
Bố già


2

Tôi biết có thể có một số cách để làm điều này, tôi đang sử dụng Core 3.1 và đang tìm kiếm tùy chọn tối ưu / sạch hơn và cuối cùng tôi đã làm điều này:

  1. Lớp khởi động của tôi là mặc định
public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}
  1. Appsinstall.json của tôi là như thế này
{
  "CompanySettings": {
    "name": "Fake Co"
  }
}
  1. Lớp của tôi là Trình điều khiển API, vì vậy trước tiên tôi đã thêm tham chiếu bằng cách sử dụng giao diện IConfiguration
using Microsoft.Extensions.Configuration;

public class EmployeeController 
{
    private IConfiguration _configuration;
    public EmployeeController(IConfiguration configuration)
    {
        _configuration = configuration;
    }
}
  1. Cuối cùng tôi đã sử dụng phương thức GetValue
public async Task<IActionResult> Post([FromBody] EmployeeModel form)
{
    var companyName = configuration.GetValue<string>("CompanySettings:name");
    // companyName = "Fake Co"
}

0

Trong 8-2017, Microsoft đã ra mắt với System.Configuration.NET CORE v4.4. Hiện tại xem trước v4.5 và v4.6.

Đối với những người trong chúng ta, những người làm việc về việc chuyển đổi từ .Net Framework sang CORE, đây là điều cần thiết. Nó cho phép giữ và sử dụng app.configcác tập tin hiện tại , có thể được truy cập từ bất kỳ hội đồng nào. Nó thậm chí có thể là một thay thế choappsettings.json , vì Microsoft nhận ra sự cần thiết của nó. Nó hoạt động giống như trước đây trong FW. Có một sự khác biệt:

Trong các ứng dụng web, [ví dụ ASP.NET CORE WEB API] bạn cần phải sử dụng app.configkhông web.config cho bạn appSettingshay configurationSection. Bạn có thể cần sử dụng web.confignhưng chỉ khi bạn triển khai trang web của mình qua IIS. Bạn đặt các cài đặt dành riêng cho IIS vàoweb.config

Tôi đã thử nghiệm nó với netst Chuẩn20 DLL và Asp.net Core Web Api và tất cả đều hoạt động.


0

Sử dụng mẫu Tùy chọn trong ASP.NET Core là cách để đi. Tôi chỉ muốn thêm, nếu bạn cần truy cập các tùy chọn trong startup.cs của mình , tôi khuyên bạn nên làm theo cách này:

CosmosDbOptions.cs:

public class CosmosDbOptions
{
    public string ConnectionString { get; set; }
}

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // This is how you can access the Connection String:
    var connectionString = Configuration.GetSection(nameof(CosmosDbOptions))[nameof(CosmosDbOptions.ConnectionString)];
}

Vì vậy, nếu tôi có toàn bộ tiểu mục với hàng tá giá trị cấu hình mà tôi cần truy cập trong ConfigureService thì tôi cần phải làm điều đó cho tất cả chúng? Không có cách nào khác để làm điều này thông qua mẫu IOptions? Tôi cần đưa phương thức này vào một phương thức mở rộng tĩnh nơi tôi đang định cấu hình xe buýt vận chuyển khối lượng lớn của mình. Ngoài ra, những gì về đề xuất này của Microsoft về việc không sử dụng mẫu IOptions trong ConfigureService docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/ đấm
kuldeep

Tôi không sử dụng IOPtions trong ConfigureService tại đây ...
Martin Brandl

-3

Tôi phải đọc các thông số riêng bằng cách khởi động.
Điều đó phải có ở đó trước khi Webhost được khởi động (vì tôi cần có thể nghe url / IP và cổng từ tệp tham số và áp dụng nó vào Webhost). Hơn nữa, tôi cần các cài đặt công khai trong toàn bộ ứng dụng.

Sau khi tìm kiếm một lúc (không tìm thấy ví dụ đầy đủ, chỉ có đoạn trích) và sau nhiều lần thử và lỗi khác nhau, tôi đã quyết định thực hiện theo cách cũ của "với một tệp .ini riêng.
Vì vậy, nếu bạn muốn sử dụng sở hữu tệp .ini và / hoặc đặt "để nghe url / IP" của riêng bạn và / hoặc cần các cài đặt công khai, đây là dành cho bạn ...

Ví dụ hoàn chỉnh, hợp lệ cho lõi 2.1 (mvc):

Tạo một tệp .ini - ví dụ:

[Khởi động]
URL = http://172.16.1.201:22222
[Tham số]
* Dummy1 = gew7623
Dummy1 = true
Dummy2 = 1

theo đó Dummyx chỉ được đưa vào làm ví dụ cho các loại ngày khác ngoài chuỗi (và cũng để kiểm tra trường hợp Sai sai param param (xem mã bên dưới).

Đã thêm một tệp mã trong thư mục gốc của dự án, để lưu trữ các biến toàn cục:

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... 
}

Đã thay đổi mã trong chương trình.cs (trước CreatWebhostBuilder ()):

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

    }
}

Cách này:

  • Cấu hình ứng dụng của tôi được tách ra khỏi appsinstall.json và tôi không sợ phụ, nếu MS thay đổi trong các phiên bản trong tương lai ;-)
  • Tôi có cài đặt của mình trong các biến toàn cục
  • Tôi có thể đặt "để nghe url" cho từng thiết bị, ứng dụng chạy trên (máy dev của tôi, máy chủ mạng nội bộ và máy chủ internet)
  • Tôi có thể tắt cài đặt, theo cách cũ (chỉ cần đặt * trước)
  • Tôi có thể phản ứng, nếu có gì đó không đúng trong tệp .ini (ví dụ: loại không khớp)
    Nếu - ví dụ - một loại sai được đặt (ví dụ: * Dummy1 = gew7623 được kích hoạt thay vì Dummy1 = true) máy chủ hiển thị màu đỏ thông tin trên bảng điều khiển (bao gồm ngoại lệ) và tôi cũng có thể phản ứng trong ứng dụng (GV.bFehler_Ini ist được đặt thành đúng, nếu có lỗi với .ini)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.